该案例的实现效果是在一个场景中绘制地板、大球、小球、公转自转和相机的移动,其中结合了OpenGL中大部分知识点,我们先看看最终的效果
效果图.gif
可以看到,这最终效果主要有以下3部分构成:
1.绿色的地板
2.自转的红色大球
3.50个随机分布的蓝色小球以及1个围绕大球公转的动态小球
下面我们主要说说这三部分是如何绘制的
地板
地板的绘制主要分为两步:
1.SetupRC函数:准备地板的顶点数据
2.RenderScene函数:利用平面着色器绘制地板
//SetupRC中
floorBatch.Begin(GL_LINES, 324);
for(GLfloat x = -20.0; x <= 20.0f; x+= 0.5) {
floorBatch.Vertex3f(x, -0.55f, 20.0f);
floorBatch.Vertex3f(x, -0.55f, -20.0f);
floorBatch.Vertex3f(20.0f, -0.55f, x);
floorBatch.Vertex3f(-20.0f, -0.55f, x);
}
floorBatch.End();
//RenderScene中
static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f};//颜色值
shaderManager.UseStockShader(GLT_SHADER_FLAT,
transformPipeline.GetModelViewProjectionMatrix(),
vFloorColor);
floorBatch.Draw();
大球
绘制大球,并实现其自转功能,主要步骤如下:
1.SetupRC函数:利用系统类创建大球
2.RenderScene函数:首先设置一个定时器,通过这个定时器得到弧度,再通过大球的绘制配合旋转方法实现大球的自转。这里为了可以直观的看到效果,我对大球设置了一个线填充
gltMakeSphere(torusBatch, 0.3f, 40, 80);//后三个为球半径,片段数,堆叠数
static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
//设置点光源位置
M3DVector4f vLightPos = {0,10,10,1};
modelViewMatrix.Translate(0.0f, 0.2f, -3.0f);
modelViewMatrix.PushMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//设置线填充
modelViewMatrix.Rotate(yRot, 0, 1, 0);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transform Pipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vTorusColor);
torusBatch.Draw();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
modelViewMatrix.PopMatrix();
小球
大球绘制完后,我们继续绘制小球,方法如下:
1.SetupRC函数:初始化小球数据
2.RenderScene函数:首先绘制50个静态小球,每绘制一个小球都需要进行push和pop操作,再矩阵通过堆栈记录旋转+平移的变换,绘制动态小球。
gltMakeSphere(sphereBatch, 0.1f, 13, 26);
for (int i = 0; i < NUM_SPHERES; i++) {
//y轴不变,X,Z产生随机值
GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
//对spheres数组中的每一个顶点,设置顶点数据
spheres[i].SetOrigin(x, 0.0f, z);
}
//绘制静态小球
for (int i = 0; i < NUM_SPHERES; i++) {
modelViewMatrix.PushMatrix();
modelViewMatrix.MultMatrix(spheres[i]); shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSpereColor);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
// 矩阵堆栈记录旋转,平移操作
modelViewMatrix.Rotate(yRot * -1.0f, 0, 1, 0);
modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSpereColor);
sphereBatch.Draw();
注:这里的rotate+tranalate的顺序是不能互换的,因为矩阵相乘是叉乘,不满足交换律,修改后会产生不同的效果,具体大家可以自己修改代码尝试一下。
完整的代码见OpenGL整合。











网友评论