在上一篇文章中,我们已经画出了一个看上去没什么问题的圆圈,并且怎么转动也没出现奇奇怪怪的显示问题。
今天我们就来为这个圆圈贴图(加上纹理)。
这次是在上一篇文章的基础上,加点代码,来实现这样的效果。
image.png
先说说我这次都做了什么
1.把圆圈换成圆
2.给绘制出来的图像上了纹理
在上一篇文章的基础上多了这些内容
1.一张纹理图
image.png
2.一个用于绑定纹理的ID
//纹理变量,一般使用无符号整型
GLuint textureID;
3.一个加载纹理的方法
参数说明:
szFileName
:纹理文件的名称
minFilter
:需要缩小的过滤器
magFilter
:需要放大的过滤器
wrapMode
:纹理坐标环绕模式
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
//这些用来存储纹理数据
GLbyte *pBits;
int nWidth, nHeight, nComponents;
GLenum eFormat;
//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;
}
4.应用textureID & LoadTGATexture
void SetupRC()
{
//黑色背景
glClearColor(0, 0, 0, 1);
//视角往前移动
viewFrame.MoveForward(7);
//初始化管理器
shaderManager.InitializeStockShaders();
//分配纹理对象 参数1:纹理对象个数,参数2:纹理对象指针
glGenTextures(1, &textureID);
//绑定纹理状态 参数1:纹理状态2D 参数2:纹理对象
glBindTexture(GL_TEXTURE_2D, textureID);
//将TGA文件加载为2D纹理。
//参数1:纹理文件名称
//参数2&参数3:需要缩小&放大的过滤器
//参数4:纹理坐标环绕模式
LoadTGATexture("MoonLike.tga", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, GL_CLAMP_TO_EDGE);
//画圈
gltMakeSphere(torusBatch, 1, 40, 20);
}
//渲染场景
void RenderScene()
{
//清理各种缓存
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//开启表⾯面剔除(默认背⾯面剔除)
glEnable(GL_CULL_FACE);
//用户指定哪个环绕顺序为正面 可选值为:GL_CW、 GL_CCW
//默认传入GL_CCW
glFrontFace(GL_CCW);
//⽤户选择剔除哪个面(正面/背面)
//默认为背面
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
//矩阵压栈,注意这里push了viewFrame进去
modelViewMatix.PushMatrix(viewFrame);
//定义光源位置&漫反射颜色
static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
static GLfloat vLightPos[] = { 0.0f, 3.0f, 0.0f, 1.0f };
glBindTexture(GL_TEXTURE_2D, textureID);
/*点光源着色器
参数1:GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF(着色器标签)
参数2:模型视图矩阵
参数3:投影矩阵
参数4:视点坐标系中的光源位置
参数5:基本漫反射颜色
参数6:图形颜色(用纹理就不需要设置颜色。设置为0)
*/
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
modelViewMatix.GetMatrix(),
transformPipeline.GetProjectionMatrix(),
vLightPos,
vWhite,
0);
//绘制
torusBatch.Draw();
//出栈
modelViewMatix.PopMatrix();
glutSwapBuffers();
}
至此,就可以画出文章刚开始时的月亮了,有兴趣的朋友也可以改变一下图元,可以换成各种形状,比如:
image.png
网友评论