深度测试的理解
隐藏面消除
在绘制3D场景的时候,我们需要决定哪些部分是对观察者可见的,或者哪些部分是对观察者不可见的,对于不可见的部分,应该及早丢弃,例如在一个不透明的墙壁后,就不应该渲染,这种情况叫做‘隐藏面消除’(Hidden Surface elimination)
通常情况下,渲染的图形都会进行光栅化,所以在进行3D变换的时候,渲染的图形会被移到前部的图形遮挡,因此会出现下图的情况。
解决方案
- 油画法
- 先绘制场景中的里观察者较远的物体,在绘制较近的物体
- 按照图片示例,是红-》黄-》灰的顺序,但是这种图形处理的效率会比较低,必须在发生重叠的地方对每个像素点进行多次的写操作,开销会变高
- 正背面剔除法 Face Culling
- 理解起来就是从观察者的角度,并不能看到所有的面,因此可以通过OpenGL来过滤掉看不到的面,只渲染可以看到的面。剔除看不到的面就能提高性能,避免上面被覆盖的情况
1.//开启正背面剔除
2 glEnable(GL_CULL_FACE);
3 //2.关闭
4 glDisable(GL_CULL_FACE);
5 //3. 指定剔除面:mode GL_FRONT GL_BACK GL_FRONT_AND_BACK
6 void glCullFace(GLenum mode);
案例理解
001 图形变换
// 召唤场景
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//压栈
modelViewMatrix.PushMatrix();
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
//矩阵乘以矩阵堆栈的顶部矩阵,相乘的结果随后简存储在堆栈的顶部
modelViewMatrix.MultMatrix(mCamera);
M3DMatrix44f mObjectFrame;
//只要使用 GetMatrix 函数就可以获取矩阵堆栈顶部的值,这个函数可以进行2次重载。用来使用GLShaderManager 的使用。或者是获取顶部矩阵的顶点副本数据
objectFrame.GetMatrix(mObjectFrame);
//矩阵乘以矩阵堆栈的顶部矩阵,相乘的结果随后简存储在堆栈的顶部
modelViewMatrix.MultMatrix(mObjectFrame);
/* GLShaderManager 中的Uniform 值——平面着色器
参数1:平面着色器
参数2:运行为几何图形变换指定一个 4 * 4变换矩阵
--transformPipeline.GetModelViewProjectionMatrix() 获取的
GetMatrix函数就可以获得矩阵堆栈顶部的值
参数3:颜色值(黑色)
*/
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
switch(nStep) {
case 0:
//设置点的大小
glPointSize(4.0f);
pointBatch.Draw();
glPointSize(1.0f);
break;
case 1:
//设置线的宽度
glLineWidth(2.0f);
lineBatch.Draw();
glLineWidth(1.0f);
break;
case 2:
glLineWidth(2.0f);
lineStripBatch.Draw();
glLineWidth(1.0f);
break;
case 3:
glLineWidth(2.0f);
lineLoopBatch.Draw();
glLineWidth(1.0f);
break;
case 4:
DrawWireFramedBatch(&triangleBatch);
break;
case 5:
DrawWireFramedBatch(&triangleStripBatch);
break;
case 6:
DrawWireFramedBatch(&triangleFanBatch);
break;
}
//还原到以前的模型视图矩阵(单位矩阵)
modelViewMatrix.PopMatrix();
// 进行缓冲区交换
glutSwapBuffers();
}
002 甜甜圈
//窗口改变
void ChangeSize(int w, int h)
{
//1.防止h变为0
if(h == 0)
h = 1;
//2.设置视口窗口尺寸
glViewport(0, 0, w, h);
//3.setPerspective函数的参数是一个从顶点方向看去的视场角度(用角度值表示)
// 设置透视模式,初始化其透视矩阵
viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);
//4.把透视矩阵加载到透视矩阵对阵中
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//5.初始化渲染管线
transformPipeline.SetMatrixStacks(modelViewMatix, projectionMatrix);
}