渲染世界的OPENGL<14>纹理进阶-多重纹理

本文介绍了OpenGL如何实现多重纹理,包括纹理单元的切换、纹理坐标处理,并通过一个示例展示了如何结合不同纹理创建复杂的视觉效果,如反射和环境映射。在示例中,将二维纹理与立方体贴图纹理相结合,利用着色器调整了反射的明暗效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多重纹理
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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值