该案例主要是对常见的图元连接方式的运用,常见的图元在该链接中已经讲过,各图元的效果图如下:
在之前的博客里面有完成一个简单的三角形案例,在该案例中使用三个顶点绘制了一个三角形。
在该案例中,主要使用到几个函数:
- main函数:函数入口;
- ChangeSize函数:设置视口大小,也可以该函数中设置投影方式等。
- SetupRC函数:设置顶点数据以及图元装配方式。
- RenderScene函数:用于图形绘制,可手动触发也由系统触发。
- SpecialKeys函数:针对特殊键位处理的回调函数。
- KeyPressFunc函数:针对空格处理的回调函数。
- DrawWireFrameBatch函数:用于立体图形的填充和边框绘制。
接下来,根据我们所需要绘制的图形,对各函数进行讲解。
1. 点、线段、线环
绘制点、线段、线环这三种方式都较为简单。
- 在SetupRC函数里面设置顶点数据,图元装配方式等,并将数据copy到着色器。
//顶点数据
GLfloat vCoast[9] = {
3,3,0,0,3,0,3,0,0
};
//图元装配选择点
pointBatch.Begin(GL_POINTS, 3);
pointBatch.CopyVertexData3f(vCoast);
pointBatch.End();
//图元装配选择线
lineBatch.Begin(GL_LINES, 3);
lineBatch.CopyVertexData3f(vCoast);
lineBatch.End();
//图元装配选择线段
lineStripBatch.Begin(GL_LINE_STRIP, 3);
lineStripBatch.CopyVertexData3f(vCoast);
lineStripBatch.End();
//图元装配选择线环
lineLoopBatch.Begin(GL_LINE_LOOP, 3);
lineLoopBatch.CopyVertexData3f(vCoast);
lineLoopBatch.End();
- 在RenderScene函数里面进行绘制
//点
glPointSize(4.0f);
pointBatch.Draw();
glPointSize(1.0f);
//线
glPointSize(4.0f);
lineBatch.Draw();
glPointSize(1.0f);
//线段
glPointSize(4.0f);
lineStripBatch.Draw();
glPointSize(1.0f);
//线环
glPointSize(4.0f);
lineLoopBatch.Draw();
glPointSize(1.0f);
2. 绘制金字塔、六边形、圆环
- changeSize函数
在前面的案例里面,changeSize主要用来设置视口大小,而在本案例中,还需要设置投影方式。
由于后面需要获取模型视图投影矩阵,因此,先在这个函数里面初始化模型视图矩阵堆栈,并往栈里面写入一个单元矩阵。
viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 500.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
modelViewMatrix.LoadIdentity();
- SetupRC函数
- 将模型视图矩阵和投影矩阵放到变换管道中,变换管道的作用是能帮助快速进行矩阵相乘,在RenderScene函数中可以直接通过变换管道的Get方法得到相应的矩阵。
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
2. 设置观察者的位置
cameraFrame.MoveForward(-30.0f);
- RenderScene函数
-
- RenderScene函数中,可以对模型视图矩阵堆栈中再添加一个单元矩阵,这主要是为了绘制完成后,矩阵可以恢复至最开始的样子。
modelViewMatrix.PushMatrix();
- 2.将cameraFrame构建为观察者矩阵,并将它与模型视图矩阵堆栈的栈顶相乘,得到的结果再压入模型视图矩阵堆栈。
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);
-
- 将objectFrame构建为物体矩阵,并将它与模型视图矩阵堆栈的栈顶相乘,得到的结果再压入模型视图矩阵堆栈。
M3DMatrix44f mObject;
objectFrame.GetMatrix(mObject);
modelViewMatrix.MultMatrix(mObject);
-
- 然后利用固定管线渲染图形,在图像渲染完成后,将栈中模型视图矩阵pop,恢复其初始状态。
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
modelViewMatrix.PopMatrix();
3. 给金字塔增加边框
在步骤二的时候,已经将金字塔绘制到屏幕上,但是有个问题,由于没有边框,所以并不能通过屏幕直接看出来那是金字塔,这个时候就得给金字塔加上边框,才能显得图形更加立体。
-
- 开启多边形绘制,设置偏移量
glPolygonOffset(-1.0f, -1.0f);
glEnable(GL_POLYGON_OFFSET_LINE);
-
- 开启抗锯齿功能,使得线条更加平滑
glEnable(GL_LINE_SMOOTH);
-
- 开启颜色混合
glEnable(GL_BLEND);
-
- 绘制边框、设置线条宽度
//绘制线框几何黑色版 三种模式,实心,边框,点,可以作用在正面,背面,或者两面
//通过调用glPolygonMode将多边形正面或者背面设为线框模式,实现线框渲染
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//设置线条宽度
glLineWidth(2.5f);
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
pBatch->Draw();
-
- 还原设置属性
//通过调用glPolygonMode将多边形正面或者背面设为全部填充模式
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_POLYGON_OFFSET_LINE);
glLineWidth(1.0f);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);