
本文共 6697 字,大约阅读时间需要 22 分钟。
OpenGL纹理技术指南
矩形纹理
矩形纹理在OpenGL中提供了一种高效的纹理渲染方式。与标准纹理(GL_TEXTURE_2D
)不同,矩形纹理(GL_TEXTURE_RECTANGLE
)具有以下特点:
纹理坐标范围:矩形纹理的纹理坐标不像普通纹理那样在[0,1]范围内,而是基于像素坐标进行计算,例如纹理坐标(5,19)代表从左数第六列,从上数第20行的像素。
倍数贴图支持:矩形纹理不支持倍数贴图(Mip贴图),因此需要手动生成倍数层次。
环绕模式:支持标准的环绕模式(GL_texture_wrap_mode
),包括Repeat、Clamp到边缘和Mirror等。
纹理压缩:不支持纹理压缩,必须使用原始图片数据。
加载矩形纹理
以下是加载矩形纹理(GL_TEXTURE_RECTANGLE
)的代码示例:
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode) { GLbyte *pBits; int nWidth, nHeight, nComponents; GLenum eFormat; // 读取纹理数据 pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat); if (!pBits) { 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); // 设置像素存储属性 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // 创建纹理 glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits); free(pBits); // 如果启用倍数贴图生成 if (minFilter == GL_LINEAR_MIPMAP_LINEAR || minFilter == GL_LINEAR_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_LINEAR || minFilter == GL_NEAREST_MIPMAP_NEAREST) { glGenerateMipmap(GL_TEXTURE_2D); } return true;}
使用矩形纹理
将矩形纹理加载到uiTextures[3]
纹理对象中:
// 加载Logo纹理// glBindTexture(GL_TEXTURE_RECTANGLE, uiTextures[3]);LoadTGATexture("OpenGL-Logo.tga", GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE);
渲染设置
准备好正交投影矩阵,并创建一个GLBatch
批次对象。纹理坐标的设置方式如下:
// 定义纹理坐标int x = 500; int y = 155; int width = 300; int height = 155;// 创建批次对象logoBatch.Begin(GL_TRIANGLE_FAN, 4, 1);// 上左角位置logoBatch.MultiTexCoord2f(0, 0.0f, height);logoBatch.Vertex3f(x, y, 0.0f);// 下左角位置logoBatch.MultiTexCoord2f(0, 0.0f, 0.0f);logoBatch.Vertex3f(x, y - height, 0.0f);// 下右角位置logoBatch.MultiTexCoord2f(0, width, 0.0f);logoBatch.Vertex3f(x + width, y - height, 0.0f);// 上右角位置logoBatch.MultiTexCoord2f(0, width, height);logoBatch.Vertex3f(x + width, y, 0.0f);// 结束批次绘制logoBatch.End();
片段着色器和顶点着色器
// 矩形纹理片段着色器Shader代码如下:#version 140out vec4 vFragColor;uniform sampler2DRect rectangleImage;smooth in vec2 vVaryingTexCoord;void main() { vFragColor = texture(rectangleImage, vVaryingTexCoord);}
// 矩形纹理顶点着色器Shader代码如下:#version 140in vec4 vVertex;in vec2 vTexCoord;uniform mat4 mvpMatrix;smooth out vec2 vVaryingTexCoord;void main() { vVaryingTexCoord = vTexCoord; gl_Position = mvpMatrix * vVertex;}
立方体贴图
立方体贴图(Cubemap)由六个面组成,每个面是一个正方形的2D图像。立方体贴图用于模拟真实环境中的反射和遮挡。
加载立方体贴图
立方体贴图的标量类型包括:
GL_TEXTURE_CUBE_MAP_POSITIVE_X
GL_TEXTURE_CUBE_MAP_NEGATIVE_X
GL_TEXTURE_CUBE_MAP_POSITIVE_Y
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
GL_TEXTURE_CUBE_MAP_POSITIVE_Z
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
.
例如,加载正X方向的贴图:
GLubyte *pBits = gltReadTGABits("positive_x.tga", &nWidth, &nHeight, &nComponents, &eFormat);glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);free(pBits);
设置纹理参数时,需要将目标类型设置为GL_TEXTURE_CUBE_MAP
。例如:
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
生成倍数贴图
立方体贴图支持生成倍数贴图(Mip贴图):
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
立方体贴图的纹理坐标是三维的,环绕模式需要同时设置三个方向:
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
多重纹理
OpenGL支持多个纹理单元的绑定,使得可以将多个纹理应用于同一个几何对象。使用多重纹理可以创造更复杂的视觉效果。
检查纹理单元数量
获取支持的纹理单元数量:
GLint iUnits;glGetIntegerv(GL_MAX_TEXTURE_UNITS, &iUnits);
�rys 使用多重纹理
切换到第2个纹理单元并绑定纹理对象:
glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, textureID);
在渲染时,需要注意当前活动的纹理单元。
多纹理坐标
GLBatch
批次对象支持设置多个纹理坐标:
GLBatch::Begin(GLフェ lienprimitive, GLuint nVerts, GLuint nTextureUnits = 0);
可以使用以下方法设置纹理坐标:
一次复制纹理坐标:
void GLBatch::CopyTexCoordData2f(M3DVector2f *vTexCoords, GLuint uiTextureLayer);
逐个设置纹理坐标:
void GLBatch::MultiTexCoord2f(GLuint texture, GLclampf s, GLclampf t);void GLBatch::MultiTexCoord2fv(GLuint texture, M3DVector2f vTexCoord);
多重纹理示例
// 初始化多重纹理GLuint texture1, texture2;glGenTextures(2, &texture1, &texture2);glBindTexture(GL_TEXTURE_2D, texture1);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texture2);// 渲染使用多重纹理的几何对象
点精灵(Point Sprite)
点精灵是一个特殊的纹理类型,每个顶点都会生成一个小的点形象。点精灵的纹理坐标使用gl_PointCoord
内置变量。
定义点精灵大小
设置点精灵大小:
glPointSize(5.0);
启用顶点着色器定义点大小:
glEnable(GL_PROGRAM_POINT_SIZE);
在片段着色器中设定点大小:
uniform float gl_PointSize;out vec4 vFragColor;void main() { vFragColor = vec4(1.0, 1.0, 1.0, 1.0);}
点精灵旋转
为了实现点精灵的旋转,可以在顶点着色器中计算旋转矩阵并将其传递到片段着色器。
uniform float angle;uniform mat2 rotationMatrix;void main() { vVertex.x = (rotationMatrix[0] * vVertex.x) + (rotationMatrix[1] * vVertex.y); vVertex.y = (rotationMatrix[2] * vVertex.x) + (rotationMatrix[3] * vVertex.y); gl_Position = MVPMatrix * vVertex;}
纹理数组
纹理数组(GL_TEXTURE_2D_ARRAY
)允许将多张纹理切换到同一个纹理对象中,特别适用于动态图像。
加载纹理数组
生成纹理数组:
GLuint moonTexture;glGenTextures(1, &moonTexture);glBindTexture(GL_TEXTURE_2D_ARRAY, moonTexture);
设置纹理参数:
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
加载纹理数组数据:
void glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *data);glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 64, 64, 29, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);for (int i = 0; i < 29; i++) { char cFile[32]; sprintf_s(cFile, "moon%02d.tga", i); GLbyte *pBits = gltReadTGABits(cFile, &nWidth, &nHeight, &nComponents, &eFormat); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, nWidth, nHeight, 1, GL_BGRA, GL_UNSIGNED_BYTE, pBits); free(pBits);}
访问纹理数组
在片段着色器中使用纹理数组:
uniform sampler2DArray moonImage;smooth in vec3 vMoonCoords;void main() { vec2 st = vMoonCoords.st; float index = vMoonCoords.p; vec3 color = texture2DArray(moonImage, st, index); vFragColor = color;}
纹理代理
纹理代理(GL_PROXY_TEXTURE
)用于检查硬件支持的纹理格式和参数。
创建纹理代理
glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGB, 2048, 4096, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
检查硬件支持
int height;glGetTexLevelParameter(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
如果height
返回0,说明不支持该纹理尺寸。
发表评论
最新留言
关于作者
