多重纹理
OPENGL允许我们将独立的纹理对象绑定到一些可用的纹理单元上,从而提供了将两个或更多纹理同时应用到几何图形上的能力。我们可以对实现进行查询:
GLint iUnits;
glGetIntegerv(GL_MAX_TEXXTURE_UNITS, &iUnits);
默认情况下,第一个纹理单元为活动的纹理单元。所有纹理绑定操作都会影响当前活动的纹理单元。我们可以通过调用以纹理单元标识符为变量的glActiveTexture来改变当前纹理单元。
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID);
//要切换到第二个纹理单元并且将它绑定到指定的纹理上。
(1)多重纹理坐标
通过对纹理坐标进行插值,我们可以吧纹理应用到几何图形上面。我们还可以计算纹理坐标,就像在前面示例当中为天空盒做的一切一样。或者可以为每个纹理提供独立的一组纹理坐标;毕竟这只不过是在我们批次中增加一组属性而已。
默认情况下,GLBatch类不会以一个属性数组的形式提供任何纹理坐标。不过在调用以nTextureUnits为参数的Begin函数时,我们最多可以指定4组纹理坐标。
void GLBatch::Begin(GLenum primitive, GLuint nVerts, GLuint nTextureUnits=0);
有两个函数可以提供纹理坐标。第一个函数是CopyTexCoordData2f,速度最快的,因为会一次复制整个一组纹理坐标。
void GLBatch::CopyTexCoordData2f(M3DVector2f *vTexCoords, GLuint uiTextureLayer);
第二个函数则是使用较慢的每次一个顶点的接口,与立即模式类似。
我们可以通过两种方式指定一个二维纹理坐标:
void GLBatch::MultiTexCoord2f(GLuint texture, GLclampf s, GLclamf t);
void GLBacth::MultiTexCoordfv(GLuint texture, M3DVector2f vTexCoord);
(2)多重纹理示例
纹理坐标可以以几乎无限多的方式进行组合,有种类繁多的技术采用在一个着色器中一次使用两个或多个纹理方式。
这个示例是多重纹理的组合演示,针对这个示例,我将会对这个项目的完整代码进行详细分析。
在上一章的反射周围环境的球体,再加上晦暗纹理贴图。
我们将这个二维纹理绑定到纹理单元GL_TEXTURE1上,然后用取自晦暗纹理的纹理颜色乘以立方体贴图纹理的颜色。在晦暗纹理较深的地方,反射会变暗。而在晦暗纹理比较浅或者接近白色的地方,对反射纹理几乎没有影响。
#version 130
// 输入每个顶点的坐标以及法线坐标
in vec4 vVertex;
in vec3 vNormal;
//为晦暗纹理将要使用的二维纹理坐标添加属性
in vec2 vTexCoords;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
uniform mat4 mInverseCamera;
smooth out vec3 vVaryingTexCoord;
//在添加完二维纹理坐标添加属性之后,我们需要对其进行插值,
//设置一组坐标,这组坐标能够在顶点之间平滑的进行插值。
smooth out vec2 vTarnishCoords;
void main(void)
{
//视觉坐标系当中的法向量
vec3 vEyeNormal = normalMatrix * vNormal;
// 视觉坐标系当中的顶点坐标位置
vec4 vVert4 = mvMatrix * vVertex;
vec3 vEyeVertex = normalize(vVert4.xyz / vVert4.w);
// 得到反射向量
vec4 vCoords = vec4(reflect(vEyeVertex, vEyeNormal), 1.0);
// 根据摄像机进行旋转
vCoords = mInverseCamera * vCoords;
vVaryingTexCoord.xyz = normalize(vCoords.xyz);
//最后将这些属性分配给插值变量即可。
vTarnishCoords = vTexCoords.st;
// 几何变换
gl_P