转自【翻译】NeHe OpenGL 教程

前言

声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改。对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢。

NeHe OpenGL第四十四课:3D光晕

3D 光晕

当镜头对准太阳的时候就会出现这种效果,模拟它非常的简单,一点数学和纹理贴图就够了。好好看看吧。

 

大家好,欢迎来到新的一课,在这一课中我们将扩展glCamera类,来实现镜头光晕的效果。在日常生活中,当我们对着光源看时,会发现强烈的反光。

为了完成这个效果,我们需要一些数学知识。首先,我们需要一些函数,用来检测某个点或球是否在当前的视景体内。接着我们需要一些纹理作为我们的光晕效果,我们可以把它贴在显示面上。

在我的上一个摄像机类里把下面函数写错了,现在修正如下:

 

void glCamera::SetPrespective(){ GLfloat Matrix[16];

glVector v;

// 根据当前的偏转角旋转视线

glRotatef(m_HeadingDegrees, 0.0f, 1.0f, 0.0f);

glRotatef(m_PitchDegrees, 1.0f, 0.0f, 0.0f);

// 返回模型变换矩阵

glGetFloatv(GL_MODELVIEW_MATRIX, Matrix);

// 获得视线的方向

m_DirectionVector.i = Matrix[8];

m_DirectionVector.j = Matrix[9];

m_DirectionVector.k = -Matrix[10];

// 重置矩阵

glLoadIdentity();

// 旋转场景

glRotatef(m_PitchDegrees, 1.0f, 0.0f, 0.0f);

glRotatef(m_HeadingDegrees, 0.0f, 1.0f, 0.0f);

// 设置当前摄像机的位置

v = m_DirectionVector;

v *= m_ForwardVelocity;

m_Position.x += v.i;

m_Position.y += v.j;

m_Position.z += v.k;

// 变换到新的位置

glTranslatef(-m_Position.x, -m_Position.y, -m_Position.z);

}

好了,我们现在开始吧。我将使用4个对立的纹理来制造我们的镜头光晕,第一和二个光晕图像被放置在光源处,第三和第四个图像将根据视点的位置和方向动态的生成。纹理的图像如下所示:



现在你在头脑里应该有了一个大慨地图像了吧。我们来说说何时我们应该绘制光晕,一般来说平时我们是看不见这些光晕的,只有当我们对准光源的时候才能看见这些。所以我们首先要获得视景体的数据,下面的函数可

以帮我们完成这个功能。

 

// 获得当前视景体的6个平面方程的参数void glCamera::UpdateFrustum(){    GLfloat  
clip[16]; GLfloat   proj[16];    GLfloat   modl[16];    GLfloat   t;

//返回投影矩阵

glGetFloatv( GL_PROJECTION_MATRIX, proj );

//返回模型变换矩阵

glGetFloatv( GL_MODELVIEW_MATRIX, modl );

//计算剪切矩阵,即上面两个矩阵的乘积

clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];

clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];

clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];

clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];

clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];

clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];

clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];

clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];

clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];

clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];

clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];

clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];

clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];

clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];

clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];

clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];

//提取右面的平面方程系数

m_Frustum[0][0] = clip[ 3] - clip[ 0];

m_Frustum[0][1] = clip[ 7] - clip[ 4];

m_Frustum[0][2] = clip[11] - clip[ 8];

m_Frustum[0][3] = clip[15] - clip[12];

t = GLfloat(sqrt( m_Frustum[0][0] * m_Frustum[0][0] + m_Frustum[0][1] * m_Frustum[0][1] + m_Frustum[0][2] * m_Frustum[0][2] ));

m_Frustum[0][0] /= t;

m_Frustum[0][1] /= t;

m_Frustum[0][2] /= t;

m_Frustum[0][3] /= t;

//提取左面的平面方程系数

m_Frustum[1][0] = clip[ 3] + clip[ 0];

m_Frustum[1][1] = clip[ 7] + clip[ 4];

m_Frustum[1][2] = clip[11] + clip[ 8];

m_Frustum[1][3] = clip[15] + clip[12];

t = GLfloat(sqrt( m_Frustum[1][0] * m_Frustum[1][0] + m_Frustum[1][1] * m_Frustum[1][1] + m_Frustum[1][2] * m_Frustum[1][2] ));

m_Frustum[1][0] /= t;

m_Frustum[1][1] /= t;

m_Frustum[1][2] /= t;

m_Frustum[1][3] /= t;

//提取下面的平面方程系数

m_Frustum[2][0] = clip[ 3] + clip[ 1];

m_Frustum[2][1] = clip[ 7] + clip[ 5];

m_Frustum[2][2] = clip[11] + clip[ 9];

m_Frustum[2][3] = clip[15] + clip[13];

t = GLfloat(sqrt( m_Frustum[2][0] * m_Frustum[2][0] + m_Frustum[2][1] * m_Frustum[2][1] + m_Frustum[2][2] * m_Frustum[2][2] ));

m_Frustum[2][0] /= t;

m_Frustum[2][1] /= t;

m_Frustum[2][2] /= t;

m_Frustum[2][3] /= t;

//提取上面的平面方程系数

m_Frustum[3][0] = clip[ 3] - clip[ 1];

m_Frustum[3][1] = clip[ 7] - clip[ 5];

m_Frustum[3][2] = clip[11] - clip[ 9];

m_Frustum[3][3] = clip[15] - clip[13];

t = GLfloat(sqrt( m_Frustum[3][0] * m_Frustum[3][0] + m_Frustum[3][1] * m_Frustum[3][1] + m_Frustum[3][2] * m_Frustum[3][2] ));

m_Frustum[3][0] /= t;

m_Frustum[3][1] /= t;

m_Frustum[3][2] /= t;

m_Frustum[3][3] /= t;

//提取远面的平面方程系数

m_Frustum[4][0] = clip[ 3] - clip[ 2];

m_Frustum[4][1] = clip[ 7] - clip[ 6];

m_Frustum[4][2] = clip[11] - clip[10];

m_Frustum[4][3] = clip[15] - clip[14];

t = GLfloat(sqrt( m_Frustum[4][0] * m_Frustum[4][0] + m_Frustum[4][1] * m_Frustum[4][1] + m_Frustum[4][2] * m_Frustum[4][2] ));

m_Frustum[4][0] /= t;

m_Frustum[4][1] /= t;

m_Frustum[4][2] /= t;

m_Frustum[4][3] /= t;

//提取近面的平面方程系数

m_Frustum[5][0] = clip[ 3] + clip[ 2];

m_Frustum[5][1] = clip[ 7] + clip[ 6];

m_Frustum[5][2] = clip[11] + clip[10];

m_Frustum[5][3] = clip[15] + clip[14];

t = GLfloat(sqrt( m_Frustum[5][0] * m_Frustum[5][0] + m_Frustum[5][1] * m_Frustum[5][1] + m_Frustum[5][2] * m_Frustum[5][2] ));

m_Frustum[5][0] /= t;

m_Frustum[5][1] /= t;

m_Frustum[5][2] /= t;

m_Frustum[5][3] /= t;

}

现在我们可以测试一个点或圆是否在视景体内了。下面的函数可以测试一个点是否在视景体内。 

  

BOOL glCamera::PointInFrustum(glPoint p){ int i; for(i = 0; i < 6;
i++) {  if(m_Frustum[i][0] * p.x + m_Frustum[i][1] * p.y +

m_Frustum[i][2] * p.z + m_Frustum[i][3] <= 0)  {   return(FALSE);  } } return(TRUE);}

下面的函数用来测试某个点是否位于当前场景物体的前面:

 

bool glCamera::IsOccluded(glPoint p){ GLint viewport[4];       GLdouble mvmatrix[16], projmatrix[16];

GLdouble winx, winy, winz;     GLdouble flareZ;       GLfloat bufferZ;

glGetIntegerv (GL_VIEWPORT, viewport);

glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);

glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);

// 返回顶点p在单位立方体中的位置

gluProject(p.x, p.y, p.z, mvmatrix, projmatrix, viewport, &winx, &winy, &winz);

flareZ = winz;

// 读取点(winx,winy)的深度坐标

glReadPixels(winx, winy,1,1,GL_DEPTH_COMPONENT, GL_FLOAT, &bufferZ);

// 如果深度坐标小于点的坐标,则返回true

if (bufferZ < flareZ)

return true;

//否则返回false

else

return false;

}

我们通过检测光源是否正对我们的视线来决定是否绘制光晕,但如果你的视点超过了光源的位置,则会发生看不见光晕的现象。为了避免这种现象,我们在移动视点的使用,也相应的移动我们的光源。为了在视点和光

源之间绘制多个光晕,我们需要计算之间的向量,下面的代码完成这个功能: 

  

//下面的函数完成具体的渲染光晕的任务void glCamera::RenderLensFlare(){ GLfloat Length = 0.0f;

// 如果我们的光源在我们的视线范围内,则绘制它

if(SphereInFrustum(m_LightSourcePos, 1.0f) == TRUE)

{

vLightSourceToCamera = m_Position - m_LightSourcePos; // 计算光源到我们视线的距离

Length = vLightSourceToCamera.Magnitude();

//下面三个函数计算光源位置到光晕结束位置之间的向量

ptIntersect = m_DirectionVector * Length;

ptIntersect += m_Position;

vLightSourceToIntersect = ptIntersect - m_LightSourcePos;

Length = vLightSourceToIntersect.Magnitude();

vLightSourceToIntersect.Normalize();

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA, GL_ONE);

glDisable(GL_DEPTH_TEST);

glEnable(GL_TEXTURE_2D);

首先我们需要找到光源位置和视点位置之间的向量,接下来我们需要在视线的方向设置一个插值点,这个点的距离必须和光源位置和视点位置之间的距离相等。完成以后,我们找出可以产生光晕的方向,即下图红线的

方向,在这个线上我们可以绘制我们的光晕。



  if (!IsOccluded(m_LightSourcePos)) //如果光晕可见  {   // 渲染中间的光晕   RenderBigGlow(0.60f,

0.60f, 0.8f, 1.0f, m_LightSourcePos, 16.0f);   RenderStreaks(0.60f, 0.60f, 0.8f, 1.0f, m_LightSourcePos, 16.0f);

RenderGlow(0.8f, 0.8f, 1.0f, 0.5f, m_LightSourcePos, 3.5f);

//绘制到光晕结束位置的0.1处的光晕

pt = vLightSourceToIntersect * (Length * 0.1f);

pt += m_LightSourcePos;

RenderGlow(0.9f, 0.6f, 0.4f, 0.5f, pt, 0.6f);

//绘制到光晕结束位置的0.15处的光晕

pt = vLightSourceToIntersect * (Length * 0.15f);

pt += m_LightSourcePos;

RenderHalo(0.8f, 0.5f, 0.6f, 0.5f, pt, 1.7f);

//绘制到光晕结束位置的0.175处的光晕

pt = vLightSourceToIntersect * (Length * 0.175f);

pt += m_LightSourcePos;

RenderHalo(0.9f, 0.2f, 0.1f, 0.5f, pt, 0.83f);

//绘制到光晕结束位置的0.285处的光晕

pt = vLightSourceToIntersect * (Length * 0.285f);

pt += m_LightSourcePos;

RenderHalo(0.7f, 0.7f, 0.4f, 0.5f, pt, 1.6f);

//绘制到光晕结束位置的0.2755处的光晕

pt = vLightSourceToIntersect * (Length * 0.2755f);

pt += m_LightSourcePos;

RenderGlow(0.9f, 0.9f, 0.2f, 0.5f, pt, 0.8f);

//绘制到光晕结束位置的0.4755处的光晕

pt = vLightSourceToIntersect * (Length * 0.4775f);

pt += m_LightSourcePos;

RenderGlow(0.93f, 0.82f, 0.73f, 0.5f, pt, 1.0f);

//绘制到光晕结束位置的0.49处的光晕

pt = vLightSourceToIntersect * (Length * 0.49f);

pt += m_LightSourcePos;

RenderHalo(0.7f, 0.6f, 0.5f, 0.5f, pt, 1.4f);

//绘制到光晕结束位置的0.65处的光晕

pt = vLightSourceToIntersect * (Length * 0.65f);

pt += m_LightSourcePos;

RenderGlow(0.7f, 0.8f, 0.3f, 0.5f, pt, 1.8f);

//绘制到光晕结束位置的0.63处的光晕

pt = vLightSourceToIntersect * (Length * 0.63f);

pt += m_LightSourcePos;

RenderGlow(0.4f, 0.3f, 0.2f, 0.5f, pt, 1.4f);

//绘制到光晕结束位置的0.8处的光晕

pt = vLightSourceToIntersect * (Length * 0.8f);

pt += m_LightSourcePos;

RenderHalo(0.7f, 0.5f, 0.5f, 0.5f, pt, 1.4f);

//绘制到光晕结束位置的0.7825处的光晕

pt = vLightSourceToIntersect * (Length * 0.7825f);

pt += m_LightSourcePos;

RenderGlow(0.8f, 0.5f, 0.1f, 0.5f, pt, 0.6f);

//绘制到光晕结束位置的1.0处的光晕

pt = vLightSourceToIntersect * (Length * 1.0f);

pt += m_LightSourcePos;

RenderHalo(0.5f, 0.5f, 0.7f, 0.5f, pt, 1.7f);

//绘制到光晕结束位置的0.975处的光晕

pt = vLightSourceToIntersect * (Length * 0.975f);

pt += m_LightSourcePos;

RenderGlow(0.4f, 0.1f, 0.9f, 0.5f, pt, 2.0f);

}

glDisable(GL_BLEND );

glEnable(GL_DEPTH_TEST);

glDisable(GL_TEXTURE_2D);

}

}

好了,下面的函数用来绘制四种不同的光晕 

  

//绘制Halo形的光晕void glCamera::RenderHalo(GLfloat r, GLfloat g, GLfloat b,
GLfloat a, glPoint p, GLfloat scale){ glPoint q[4];  q[0].x = (p.x -

scale);            q[0].y = (p.y - scale);

q[1].x = (p.x - scale);

q[1].y = (p.y + scale);              q[2].x =

(p.x + scale);            q[2].y = (p.y - scale);

q[3].x = (p.x + scale);

q[3].y = (p.y + scale);

glPushMatrix();              glTranslatef(p.x, p.y, p.z);

glRotatef(-m_HeadingDegrees, 0.0f, 1.0f, 0.0f); glRotatef(-m_PitchDegrees, 1.0f, 0.0f,

0.0f); glBindTexture(GL_TEXTURE_2D, m_HaloTexture);      glColor4f(r, g, b, a);

glBegin(GL_TRIANGLE_STRIP);

glTexCoord2f(0.0f, 0.0f);       glVertex2f(q[0].x, q[0].y);  glTexCoord2f(0.0f,

1.0f);  glVertex2f(q[1].x, q[1].y);  glTexCoord2f(1.0f, 0.0f);  glVertex2f(q[2].x, q[2].y);  glTexCoord2f(1.0f,

1.0f);  glVertex2f(q[3].x, q[3].y); glEnd();           glPopMatrix

();             }

//绘制Gloew形的光晕

void glCamera::RenderGlow(GLfloat r, GLfloat g, GLfloat b, GLfloat a, glPoint p, GLfloat scale)

{

glPoint q[4];

q[0].x = (p.x - scale);

q[0].y = (p.y - scale);

q[1].x = (p.x - scale);

q[1].y = (p.y + scale);

q[2].x = (p.x + scale);

q[2].y = (p.y - scale);

q[3].x = (p.x + scale);

q[3].y = (p.y + scale);

glPushMatrix();

glTranslatef(p.x, p.y, p.z);

glRotatef(-m_HeadingDegrees, 0.0f, 1.0f, 0.0f);

glRotatef(-m_PitchDegrees, 1.0f, 0.0f, 0.0f);

glBindTexture(GL_TEXTURE_2D, m_GlowTexture);

glColor4f(r, g, b, a);

glBegin(GL_TRIANGLE_STRIP);

glTexCoord2f(0.0f, 0.0f);

glVertex2f(q[0].x, q[0].y);

glTexCoord2f(0.0f, 1.0f);

glVertex2f(q[1].x, q[1].y);

glTexCoord2f(1.0f, 0.0f);

glVertex2f(q[2].x, q[2].y);

glTexCoord2f(1.0f, 1.0f);

glVertex2f(q[3].x, q[3].y);

glEnd();

glPopMatrix();

}

//绘制BigGlow形的光晕

void glCamera::RenderBigGlow(GLfloat r, GLfloat g, GLfloat b, GLfloat a, glPoint p, GLfloat scale)

{

glPoint q[4];

q[0].x = (p.x - scale);

q[0].y = (p.y - scale);

q[1].x = (p.x - scale);

q[1].y = (p.y + scale);

q[2].x = (p.x + scale);

q[2].y = (p.y - scale);

q[3].x = (p.x + scale);

q[3].y = (p.y + scale);

glPushMatrix();

glTranslatef(p.x, p.y, p.z);

glRotatef(-m_HeadingDegrees, 0.0f, 1.0f, 0.0f);

glRotatef(-m_PitchDegrees, 1.0f, 0.0f, 0.0f);

glBindTexture(GL_TEXTURE_2D, m_BigGlowTexture);

glColor4f(r, g, b, a);

glBegin(GL_TRIANGLE_STRIP);

glTexCoord2f(0.0f, 0.0f);

glVertex2f(q[0].x, q[0].y);

glTexCoord2f(0.0f, 1.0f);

glVertex2f(q[1].x, q[1].y);

glTexCoord2f(1.0f, 0.0f);

glVertex2f(q[2].x, q[2].y);

glTexCoord2f(1.0f, 1.0f);

glVertex2f(q[3].x, q[3].y);

glEnd();

glPopMatrix();

}

//绘制Streaks形的光晕

void glCamera::RenderStreaks(GLfloat r, GLfloat g, GLfloat b, GLfloat a, glPoint p, GLfloat scale)

{

glPoint q[4];

q[0].x = (p.x - scale);

q[0].y = (p.y - scale);

q[1].x = (p.x - scale);

q[1].y = (p.y + scale);

q[2].x = (p.x + scale);

q[2].y = (p.y - scale);

q[3].x = (p.x + scale);

q[3].y = (p.y + scale);

glPushMatrix();

glTranslatef(p.x, p.y, p.z);

glRotatef(-m_HeadingDegrees, 0.0f, 1.0f, 0.0f);

glRotatef(-m_PitchDegrees, 1.0f, 0.0f, 0.0f);

glBindTexture(GL_TEXTURE_2D, m_StreakTexture);

glColor4f(r, g, b, a);

glBegin(GL_TRIANGLE_STRIP);

glTexCoord2f(0.0f, 0.0f);

glVertex2f(q[0].x, q[0].y);

glTexCoord2f(0.0f, 1.0f);

glVertex2f(q[1].x, q[1].y);

glTexCoord2f(1.0f, 0.0f);

glVertex2f(q[2].x, q[2].y);

glTexCoord2f(1.0f, 1.0f);

glVertex2f(q[3].x, q[3].y);

glEnd();

glPopMatrix();

}

原文及其个版本源代码下载:

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=44

 
 

NeHe OpenGL教程 第四十四课:3D光晕的更多相关文章

  1. NeHe OpenGL教程 第三十四课:地形

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  2. NeHe OpenGL教程 第三十八课:资源文件

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  3. NeHe OpenGL教程 第三十六课:从渲染到纹理

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  4. NeHe OpenGL教程 第三十五课:播放AVI

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  5. NeHe OpenGL教程 第三十二课:拾取游戏

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. NeHe OpenGL教程 第三十九课:物理模拟

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. NeHe OpenGL教程 第三十课:碰撞检测

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  8. NeHe OpenGL教程 第四十八课:轨迹球

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  9. NeHe OpenGL教程 第四十五课:顶点缓存

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  10. NeHe OpenGL教程 第四十六课:全屏反走样

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

随机推荐

  1. hihoCoder#1014 Trie树 (前缀树)

    题目大意:给一本有n个单词的词典,有m次询问,每次询问的是该词典中有多少个单词有共同的某个前缀. 题目分析:在添加单词建立trie的时候,每经过一个节点就意味着该节点和它的各级祖先节点是某个单词的前缀 ...

  2. 【原创】Algorithms:原地归并排序

    第一次归并: a[0] a[1] a[2] a[3] a[4] a[5] a[6] 23 8 19 33 15 6 27 ↑             ↑ i     j 最开始i指向a[0],j指向a ...

  3. Android dip(dp) 与 sp的自适应问题

    本文转载于:http://www.oschina.net/question/272860_70761 今天碰到的一个问题,感觉应该其他人也会碰到,拿来分享一下. 我们都知道android在开发配置界面 ...

  4. java编程之:org.apache.commons.lang3.text.StrTokenizer

    第一个api测试:按特殊符号进行分词,并遍历每一个分词部分 public static void main(String[] args) { String aString="AB-CD-EF ...

  5. MMU讲解

    MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器.物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制 ...

  6. CentOS如何挂载硬盘

    远程SSH登录上CentOS服务器后,进行如下操作 提醒:挂载操作会清空数据,请确认挂载盘无数据或者未使用 第一步:列出所有磁盘  命令:  ll /dev/disk/by-path 提示:如果无法确 ...

  7. javascript语法体系

    5 代表此属性ECMAScript 5(一般IE9+)才支持. 图解:-- 图解:      undefined,null,NaN Infinity ECMAScript 5禁止修改     每个函数 ...

  8. unity, ugui input field

    ugui Input Field,获取输入的字符串. 错误方法: string content=inputField.FindChild("Text").text; 这样得到的是输 ...

  9. 【转】HTML - embed 与 object 之争

    在 HTML 里嵌入文本和图片之外的事物,就会用到嵌入标签,而嵌入标签在各浏览器之间的不统一,一直是让开发人员很头痛的问题.一切都要从嵌入 SUN 公司的 Applet Java 小程序开始. 当时, ...

  10. 解决IE11出现异常SCRIPT5011:不能执行已释放Script的代码

    功能概述: 最近做了一个教育科研系统,由于时间比较紧,所以能集成的功能都尽量做到了一起,其中一个上传附件的功能,在基类控制器BaseController 中建了一个Action返回视图,其他需要上传附 ...