这个案例是基于OpenGL综合练习基础上增加纹理和镜像效果的实现。

一、SetupRC函数
//6.设置地板顶点数据&地板纹理
GLfloat texSize = 10.0f;
floorBatch.Begin(GL_TRIANGLE_FAN, 4,1);
floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
floorBatch.Vertex3f(-20.f, -0.41f, 20.0f);
floorBatch.MultiTexCoord2f(0, texSize, 0.0f);
floorBatch.Vertex3f(20.0f, -0.41f, 20.f);
floorBatch.MultiTexCoord2f(0, texSize, texSize);
floorBatch.Vertex3f(20.0f, -0.41f, -20.0f);
floorBatch.MultiTexCoord2f(0, 0.0f, texSize);
floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f);
floorBatch.End();
纹理的顶点数据设置完成之后,我们就需要进行以下步骤:
1.分配纹理对象
由于使用了3种纹理,传入的纹理个数为3,并传入纹理数组
glGenTextures(3, uiTextures);
2.绑定纹理
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
3.加载纹理
LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR, GL_REPEAT);
二、加载纹理loadTGATexture函数
- 读取纹理 -- gltReadTGABits
参数说明
- 参数1:纹理文件名称
- 参数2:文件宽度地址
- 参数3:文件高度地址
- 参数4:文件组件地址
- 参数5:文件格式地址
- 返回值:pBits,指向图像数据的指针
pBits = gltReadTGABits(szFileName, &nWidth, &nHeight,
&nComponents, &eFormat);
- 设置纹理参数(S和T的环绕模式、放大/缩小的过滤方式) -- glTexParameteri。参数说明可参考OpenGL纹理API
//设置环绕方式
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。参数说明可参考OpenGL纹理API
glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth,
nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);
- 释放
free(pBits);
- 加载Mip,纹理生成所有的Mip层
参数说明
- GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
glGenerateMipmap(GL_TEXTURE_2D);
三、RenderScene函数
1. 镜面绘制
- push压栈:此处压栈的目的是由于观察者矩阵是作用于全局的,为了不影响后续图形的绘制,所以需要压栈
- 翻转Y轴:通过Scale函数,沿着y轴,从+y翻转到-y绝对值相等的坐标
- 围绕Y轴平移:平移的目的是为了镜面效果更逼真,现实中的照镜子,镜子里与镜子外也是有一定间隔的
- 指定顺时针为正面:需要绘制的-y轴的镜面部分,所以需要更改系统默认的逆时针正面,改为顺时针为正面,绘制完成后,在恢复默认设置
- 绘制镜面部分
- 恢复逆时针为正面:此处必须恢复,不然会影响后续图形的绘制
- pop出栈栈顶:恢复到堆栈栈顶是观察者矩阵的状态
//6.压栈(镜面)
modelViewMatrix.PushMatrix();
//7.---添加反光效果---
//翻转Y轴
modelViewMatrix.Scale(1.0f, -1.0f, 1.0f);
//镜面世界围绕Y轴平移一定间距
modelViewMatrix.Translate(0.0f, 0.8f, 0.0f);
//8.指定顺时针为正面
glFrontFace(GL_CW);
//9.绘制地面以外其他部分(镜面)
drawSomething(yRot);
//10.恢复为逆时针为正面
glFrontFace(GL_CCW);
//11.绘制镜面,恢复矩阵
modelViewMatrix.PopMatrix();
2.地板绘制
- 开启混合,并指定混合方程式:开启混合的目的是地板需要与镜面部分进行颜色混合,且地板需要设置一个半透明的基本色,用于颜色混合,如果不设置,则无法看到地面以下内容,将看到的是一个实体的地板
- 绑定地板纹理
- 绘制地板
- 关闭混合
//12.开启混合功能(绘制地板)
glEnable(GL_BLEND);
//13. 指定glBlendFunc 颜色混合方程式
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//14.绑定地面纹理
glBindTexture(GL_TEXTURE_2D, uiTextures[0]);
/*15.
纹理调整着色器(将一个基本色乘以一个取自纹理的单元nTextureUnit的纹理)
参数1:GLT_SHADER_TEXTURE_MODULATE
参数2:模型视图投影矩阵
参数3:颜色
参数4:纹理单元(第0层的纹理单元),level
*/
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,
transformPipeline.GetModelViewProjectionMatrix(),vFloorColor,0);
//开始绘制
floorBatch.Draw();
//关闭混合
glDisable(GL_BLEND);
3.非镜面绘制drawSomething函数
四、drawSomething函数
1.定义光源位置&漫反射颜色
static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
2.绘制悬浮小球球
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
for(int i = 0; i < NUM_SPHERES; i++) {
modelViewMatrix.PushMatrix();
modelViewMatrix.MultMatrix(spheres[i]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
modelViewMatrix.GetMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos,
vWhite,
0);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
3.绘制大球
modelViewMatrix.Translate(0.0f, 0.2f, -2.5f);
modelViewMatrix.PushMatrix();
modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
modelViewMatrix.GetMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos,
vWhite,
0);
torusBatch.Draw();
modelViewMatrix.PopMatrix();
4.绘制公转小球(公转自转)
modelViewMatrix.PushMatrix();
modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
modelViewMatrix.GetMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos,
vWhite,
0);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
Demo:
OpenGL大小球纹理镜像
网友评论