一.先看看整体效果
二.绘制流程
在OpenGl综合案例(地板,大小球,公转,自转,移动)文章中,我们绘制了大小球,公转,自转,今天我们往上面添加纹理(图片)
1.镜面效果
镜面效果其实就是把上面的翻转过来,通过纹理颜色混合达到的效果,具体流程如下:
特别说明:纹理调整着色器
纹理调整着色器(将一个基本色乘以一个取自纹理的单元nTextureUnit的纹理)
参数1:GLT_SHADER_TEXTURE_MODULATE
参数2:模型视图投影矩阵
参数3:颜色
参数4:纹理单元(第0层的纹理单元)
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_MODULATE,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor, 0);
LoadTGATexture封装函数即参数说明:
boolLoadTGATexture(constchar*szFileName,GLenumminFilter,GLenummagFilter,GLenumwrapMode)
{
GLbyte*pBits;
intnWidth, nHeight, nComponents;
GLenumeFormat;
//1.读取纹理数据
pBits =gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
if(pBits ==NULL)
return false;
//2、设置纹理参数
//参数1:纹理维度
//参数2:为S/T坐标设置模式
//参数3:wrapMode,环绕模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
//参数1:纹理维度
//参数2:线性过滤
//参数3:wrapMode,环绕模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
//3.载入纹理
//参数1:纹理维度
//参数2:mip贴图层次
//参数3:纹理单元存储的颜色成分(从读取像素图是获得)-将内部参数nComponents改为了通用压缩纹理格式GL_COMPRESSED_RGB
//参数4:加载纹理宽
//参数5:加载纹理高
//参数6:加载纹理的深度
//参数7:像素数据的数据类型(GL_UNSIGNED_BYTE,每个颜色分量都是一个8位无符号整数)
//参数8:指向纹理图像数据的指针
glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0,
eFormat,GL_UNSIGNED_BYTE, pBits);
//使用完毕释放pBits
free(pBits);
//只有minFilter 等于以下四种模式,才可以生成Mip贴图
//GL_NEAREST_MIPMAP_NEAREST具有非常好的性能,并且闪烁现象非常弱
//GL_LINEAR_MIPMAP_NEAREST常常用于对游戏进行加速,它使用了高质量的线性过滤器
//GL_LINEAR_MIPMAP_LINEAR 和GL_NEAREST_MIPMAP_LINEAR 过滤器在Mip层之间执行了一些额外的插值,以消除他们之间的过滤痕迹。
//GL_LINEAR_MIPMAP_LINEAR 三线性Mip贴图。纹理过滤的黄金准则,具有最高的精度。
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);
return true;
}
自定义函数说明:
void drawSomething(GLfloat yRot)
{
//1.定义光源位置&漫反射颜色
staticGLfloatvWhite[] = {1.0f,1.0f,1.0f,1.0f};
staticGLfloatvLightPos[] = {0.0f,3.0f,0.0f,1.0f};
//2.绘制悬浮小球球
glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
for(inti =0; 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();
}
最后附上压栈出栈理解:(仅限个人理解)modelViewMatrix.PushMatrix()&&modelViewMatrix.PopMatrix()成对出现,在观察者看到的世界中,使用OpenGL绘制图形,它是一个绘制完成后再绘制另外一个,压栈和出栈可以理解成告诉OpenGL在对应的这个区间,使用其设置的参数绘制图形,最外层的压栈出栈就是告诉OpenGL,绘制其他所有的图形都必须在这个压栈出栈区间(你可以理解成当我们没有睁开眼睛时,看不见任何物体,当我们睁开眼的时候,说看到的物体在这个区间绘制)
绑定纹理理解:
说明:(仅限个人理解)SetupRC只是初始化我们的纹理,在RenderScene告诉shaderManager每一个图形要用的对应的纹理,删除了SetupRC的绑定,则不能显示纹理,删除了RenderScene的绑定,则拿到的是上一个或者不确定的纹理
附上案例:链接: https://pan.baidu.com/s/1uSR6ltwqlXRegBJXJbQfzg 提取码: bka4