OpenGL 基础纹理
2020-07-23 本文已影响0人
_涼城
原始图像数据
像素包装
图像存储空间 = 图像的高度 * 图像宽度 * 每个像素的字节数。
OpenGL中的纹理文件格式是Targa(.TGA),这个文件格式是1个字节排列的。
认识函数
改变像素存储方式
void glPixelStorei(GLenum pname, GLint param);
恢复像素存储方式
void glPixelStoref(GLenum pname, GLfloat param);
将颜色缓存区的内容作为像素图直接读取
void glReadPixels(GLint x,GLint y,GLSizei width,GLSizei height,GLenum format,GLenum type,const void * pixels)
指定读取的缓存
void glReadBuffer(GLenum mode)
指定写入的缓存
void glWriteBuffer(GLenum mode)
载入纹理函数
1D
void glTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
2D
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
3D
void glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
更新纹理函数
1D
void glTexSubImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
2D
void glTexSubImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
3D
void glTexSubImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
插入替换纹理函数
1D
void glCopyTexSubImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
2D
void glCopyTexSubImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
纹理对象
使用函数分配纹理对象
void glGenTextures(GLsizei n ,GLuint *textTures);
绑定纹理状态
void glBindTexture(GLenum target ,GLunit texture);
删除绑定纹理对象
void glDeletgeTextures(GLsizei n, GLunit *textures);
测试纹理对象是否有效
GLboolean glIsTexture(GLunit texture);
设置纹理参数
void glTexParameterf(GLenum target, GLenum pname, GLfloat param);
void glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params);
void glTexParameteri(GLenum target, GLenum pname, GLint param);
void glTexParameteriv(GLenum target, GLenum pname, const GLint *params);
设置过滤方式
-
邻近过滤
(GL_NEAREST)
当前纹理坐标的颜色
-
线性过滤
(GL_LINEAR)
当前纹理坐标周围的纹理单元的加权平均值应用到这个纹理坐标上。
设置环绕方式
-
GL_REPEAT
重复纹理图形
-
GL_MIRRORED_REPEAT
重复图形是镜像放置
-
GL_CLAMP_TO_EDGE
纹理坐标会被约束在0到1之间,超出部分会重复纹理坐标的边缘,产生边缘被拉伸的效果。
-
GL_CLAMP_TO_BORDER
超出的坐标为用户指定的边缘颜色。
设置Mip贴图
//设置mip贴图基层
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);
//设置mip贴图最⼤层
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);
金字塔示例
加载纹理
声明纹理变量
GLuint textureID;
加载纹理图形函数
/*
szFileName 纹理文件名称
minFilter 缩小过滤器
maxFilter 放大过滤器
wrapMode 纹理坐标环绕模式
*/
bool LoadTGATexture(const char *szFileName,GLenum minFilter,GLenum maxFilter,GLenum wrapMode){
//创建指针
GLbyte * pBits;
int nWidth, nHeight,nComponents;
GLenum eFormat;
//读入纹理
pBits = gltReadTGABits(szFileName,&nWidth,&nHeight,&Components.&eFormat);
if(pBits == NULL){
return false;
}
//参数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: 缩小/放大过滤方式.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, maxFilter);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth,nHeight,0,eFormat,GL_UNSIGNED_BYTE,pBits);
free(pBits);
return true;
}
绘制金字塔坐标
//绘制金字塔
void MakePyramid(GLBatch& pyramidBatch)
{
/*1、通过pyramidBatch组建三角形批次
参数1:类型
参数2:顶点数
参数3:这个批次中将会应用1个纹理
注意:如果不写这个参数,默认为0。
*/
pyramidBatch.Begin(GL_TRIANGLES, 18, 1);
/***前情导入
2)设置纹理坐标
void MultiTexCoord2f(GLuint texture, GLclampf s, GLclampf t);
参数1:texture,纹理层次,对于使用存储着色器来进行渲染,设置为0
参数2:s:对应顶点坐标中的x坐标
参数3:t:对应顶点坐标中的y
(s,t,r,q对应顶点坐标的x,y,z,w)
pyramidBatch.MultiTexCoord2f(0,s,t);
3)void Vertex3f(GLfloat x, GLfloat y, GLfloat z);
void Vertex3fv(M3DVector3f vVertex);
向三角形批次类添加顶点数据(x,y,z);
pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);
*/
//塔顶
M3DVector3f vApex = { 0.0f, 1.0f, 0.0f };
M3DVector3f vFrontLeft = { -1.0f, -1.0f, 1.0f };
M3DVector3f vFrontRight = { 1.0f, -1.0f, 1.0f };
M3DVector3f vBackLeft = { -1.0f, -1.0f, -1.0f };
M3DVector3f vBackRight = { 1.0f, -1.0f, -1.0f };
//金字塔底部
//底部的四边形 = 三角形X + 三角形Y
//三角形X = (vBackLeft,vBackRight,vFrontRight)
//vBackLeft
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackLeft);
//vBackRight
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackRight);
//vFrontRight
pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
pyramidBatch.Vertex3fv(vFrontRight);
//三角形Y =(vFrontLeft,vBackLeft,vFrontRight)
//vFrontLeft
pyramidBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
pyramidBatch.Vertex3fv(vFrontLeft);
//vBackLeft
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackLeft);
//vFrontRight
pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
pyramidBatch.Vertex3fv(vFrontRight);
// 金字塔前面
//三角形:(Apex,vFrontLeft,vFrontRight)
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(vApex);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vFrontLeft);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vFrontRight);
//金字塔左边
//三角形:(vApex, vBackLeft, vFrontLeft)
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(vApex);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackLeft);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vFrontLeft);
//金字塔右边
//三角形:(vApex, vFrontRight, vBackRight)
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(vApex);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vFrontRight);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackRight);
//金字塔后边
//三角形:(vApex, vBackRight, vBackLeft)
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(vApex);
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackRight);
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(vBackLeft);
//结束批次设置
pyramidBatch.End();
}
在SetupRC
初始化中加载纹理并配置金字塔顶点数据
glGenTextures(1,&textureID);
/*
绑定纹理
*/
glBindTexture(GL_TEXTURE_2D,textureID);
LoadTGATexture("stone.tag",GL_LINEAR,GL_LINEAR,GL_CLAMP_TO_EDGE);
//创造金字塔pyramidBatch
MakePyramid(pyramidBatch);
最后在RenderScene
中渲染金字塔
//绑定纹理,因为我们的项目中只有一个纹理。如果有多个纹理。绑定纹理很重要
glBindTexture(GL_TEXTURE_2D, textureID);
//纹理替换矩阵着色器
/*
参数1:GLT_SHADER_TEXTURE_REPLACE(着色器标签)
参数2:模型视图投影矩阵
参数3:纹理层
*/
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE, transformPipeline.GetModelViewProjectionMatrix(), 0);
//pyramidBatch 绘制
pyramidBatch.Draw();