5

我需要使用多重纹理来渲染一个对象,但是两个纹理对于同一个对象都有不同的 uv 坐标。一种是法线贴图,另一种是光照贴图。

请提供任何有用的材料。

4

1 回答 1

6

在 OpenGL ES 2 中,无论如何您都使用着色器。因此,您可以完全自由地使用您喜欢的任何纹理坐标。只需为第二个纹理坐标对引入一个附加属性并将其委托给片段着色器,就像往常一样:

...
attribute vec2 texCoord0;
attribute vec2 texCoord1;

varying vec2 vTexCoord0;
varying vec2 vTexCoord1;

void main()
{
    ...
    vTexCoord0 = texCoord0;
    vTexCoord1 = texCoord1;
}

在片段着色器中使用各自的坐标来访问纹理:

...
uniform sampler2D tex0;
uniform sampler2D tex1;
...
varying vec2 vTexCoord0;
varying vec2 vTexCoord1;

void main()
{
    ... = texture2D(tex0, vTexCoord0);
    ... = texture2D(tex1, vTexCoord1);
}

当然,您需要为这个新属性提供数据(使用glVertexAttribPointer)。但是,如果这一切对您来说听起来很陌生,那么您应该更深入地研究 GLSL 着色器,或者您实际上使用 OpenGL ES 1。在这种情况下,您应该重新标记您的问题,我会更新我的答案。

编辑:根据您对 OpenGL ES 1 的更新,情况有点不同。我假设您已经知道如何使用单个纹理并为此指定纹理坐标,否则您应该在深入研究多纹理之前从那里开始。

glActiveTexture(GL_TEXTUREi)你可以激活第 i 个纹理单元。以下所有与纹理状态相关的操作仅涉及第 i 个纹理单元(如glBindTexture,但也glTexEnvgl(En/Dis)able(GL_TEXTURE_2D))。

对于指定纹理坐标,您仍然使用该glTexCoordPointer函数,与单个纹理一样,但glCientActiveTexture(GL_TEXTUREi)您可以选择以下调用glTexCoordPointerglEnableClientAttrib(GL_TEXTURE_COORD_ARRAY)引用的纹理单元。

所以它会是这样的:

//bind and enable textures
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, <second texture>);
glTexEnv(<texture environment for second texture>);   //maybe, if needed
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, <first texture>);
glTexEnv(<texture environment for first texture>);   //maybe, if needed
glEnable(GL_TEXTURE_2D);

//set texture coordinates
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(<texCoords for second texture>);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glTexCoordPointer(<texCoords for first texture>);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//other arrays, like glVertexPointer, ...

glDrawArrays(...)/glDrawElements(...);

//disable arrays
glClientActiveTexture(GL_TEXTURE1);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

//disable textures
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glDisable(GL_TEXTURE_2D);

我在第一个纹理之前为第二个纹理设置参数的原因只是为了在设置它们之后我们最终会激活纹理单元 0。我想我已经看到驱动程序在绘图时出现问题,并且单元 0 之外的另一个单元处于活动状态。最后保留一个或多或少的干净状态总是一个好主意,这意味着默认纹理单元 ( GL_TEXTURE0) 处于活动状态,否则不关心多重纹理的代码可能会出现问题。

编辑:如果您使用立即模式 ( glBegin/glEnd) 而不是顶点数组,那么您当然不会使用glTexCoordPointer。在这种情况下,您当然也不需要glClientAttribTexture。您只需要使用glMultiTexCoord(GL_TEXTUREi, ...)适当的纹理单元 ( GL_TEXTURE0, GL_TEXTURE1, ...) 而不是glTexCoord(...). 但是,如果我被正确告知,OpenGL ES 无论如何都没有立即模式。

于 2011-10-13T13:29:18.463 回答