我需要使用多重纹理渲染一个对象,但这两个纹理对同一对象有不同的uv坐标。一个是法线贴图,另一个是光贴图。
请提供有关这方面的有用资料
在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。在这种情况下,你应该重新标记你的问题,我会更新我的答案。
EDIT:根据您对OpenGL ES 1的更新,情况有点不同。我假设你已经知道如何使用单个纹理并为此指定纹理坐标,否则你应该在钻研多纹理之前从那里开始。
使用glActiveTexture(GL_TEXTUREi)
可以激活第i个纹理单元。以下所有与纹理状态相关的操作都只涉及到第i个纹理单元(如glBindTexture
, glTexEnv
和gl(En/Dis)able(GL_TEXTURE_2D)
)。
对于指定纹理坐标,您仍然使用glTexCoordPointer
函数,就像使用单个纹理一样,但是使用glCientActiveTexture(GL_TEXTUREi)
,您可以选择随后调用glTexCoordPointer
和glEnableClientAttrib(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
)是活跃的,否则不关心多纹理的代码可能会遇到问题。
EDIT:如果你使用直接模式(glBegin/glEnd
)而不是顶点数组,那么你当然不会使用glTexCoordPointer
。当然,在这种情况下,您也不需要glClientAttribTexture
。你只需要使用glMultiTexCoord(GL_TEXTUREi, ...)
与适当的纹理单位(GL_TEXTURE0
, GL_TEXTURE1
,…),而不是glTexCoord(...)
。但如果我被告知正确,OpenGL ES没有立即模式,无论如何。