前言:
还记得之前的案例为大家写过了一个地球月球的demo吧,光是颜色渲染是不是显得太过单调了,这次我们在其基础上来为他们渲染上纹理吧,这样我们显得高大上一点。
实现效果:
代码实现:
Step1:
//绑定纹理
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
GLbyte *bits;
int wid,hig,nCompent;
GLenum eFromat;
//读取纹理数据
bits = gltReadTGABits(szFileName, &wid, &hig, &nCompent, &eFromat);
if(bits == NULL){
return false;
}
//设置纹理参数
//环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
//过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
//载入纹理
glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, wid, hig, 0, eFromat, GL_UNSIGNED_BYTE, bits);
if(minFilter == GL_LINEAR_MIPMAP_LINEAR ||
minFilter == GL_LINEAR_MIPMAP_NEAREST ||
minFilter == GL_NEAREST_MIPMAP_LINEAR ||
minFilter == GL_NEAREST_MIPMAP_NEAREST)
{
//4.加载Mip,纹理生成所有的Mip层
//参数:GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
glGenerateMipmap(GL_TEXTURE_2D);
}
free(bits);
return true;
}
我们先把纹理绑定的核心代码给加上。
Step2:重绘制地板的模型
GLfloat texSize = 10.0f;
//创建地板批次类
floorBatch.Begin(GL_TRIANGLE_FAN, 4,1);
floorBatch.Vertex3f(-20, -0.5f, 20.f);
floorBatch.MultiTexCoord2f(0, 0, 0);
floorBatch.Vertex3f(20, -0.5f, 20.f);
floorBatch.MultiTexCoord2f(0, texSize, 0);
floorBatch.Vertex3f(20, -0.5f, -20.f);
floorBatch.MultiTexCoord2f(0, texSize, texSize);
floorBatch.Vertex3f(-20, -0.5f, -20.f);
floorBatch.MultiTexCoord2f(0, 0, texSize);
floorBatch.End();
之前我们是循环创建的以线段显示的地面,现在我们要使用纹理贴图,所以我们定义四个顶点坐标,即可。
Step3:为每个纹理进行绑定和加载
//分配纹理
glGenTextures(3, uiTextures);
//绑定纹理
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
LoadTGATexture("Marslike.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
LoadTGATexture("Moonlike.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
Step4:渲染场景
//开始渲染
void RenderScene(void) {
//清除一个或一组特定的缓冲区
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
//设置一组浮点数来各个颜色
GLfloat vRed[] = {0.0f,1.0f,0.0f,1.0f};
GLfloat vBlue[] = {0.0f,0.0f,1.0f,1.0f};
static GLfloat vFloorColor[] = { 1.0f, 1.0f, 0.0f, 0.75f};
//漫反射颜色
static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
//2.基于时间动画
static CStopWatch rotTimer;
float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
//4.光源位置
M3DVector4f vLightPos = {0.0f,10.0f,5.0f,1.0f};
modelViewMatrix.PushMatrix();
//4.加入观察者 并且压入栈顶
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);
//绑定对应纹理
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
//地板绘制
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,transformPipeline.GetModelViewProjectionMatrix(),vWhite ,0);
floorBatch.Draw();
//地球绘制
//5.使得地球和后来创建的月球位置向z轴平移向屏幕里面
modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
//6.压栈(复制栈顶)
modelViewMatrix.PushMatrix();
//7.地球自转
modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
//绑定对应纹理
glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
//8.指定合适的着色器(点光源纹理着色器)
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(), vLightPos, vWhite,0);
earthBatch.Draw();
modelViewMatrix.PopMatrix();
//月球
modelViewMatrix.PushMatrix();
//围绕地球旋转,先x自身旋转,然后再依靠距离x轴的距离,来造成旋转的假象。
modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
modelViewMatrix.Translate(1.0f, 0.0f, 0.0f);
//
//绑定对应纹理
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
//8.指定合适的着色器(点光源纹理着色器)
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
transformPipeline.GetProjectionMatrix(), vLightPos, vWhite,0);
moonBatch.Draw();
modelViewMatrix.PopMatrix();
//退出camera的矩阵
modelViewMatrix.PopMatrix();
//将在后台缓冲区进行渲染,然后在结束时交换到前台
glutSwapBuffers();
//重新渲染
glutPostRedisplay();
}
完结撒花✿✿ヽ(°▽°)ノ✿
强化练习:
上面的案例还是比较简单,那么接下来,如果我们要实现以下的效果图,该如何去做呢。
实现:月球的周围出现其他的行星,而且出现了一个类似于水面反射的效果,
大家思考下吧,下节课为大家做强化练习!!!!!!