在你问之前,是的,我已经阅读了许多教程,在这个论坛和其他论坛上发布的类似问题,等等......我已经尝试了我能找到的所有建议,但我无法让 GLSL 3.3 多纹理为我的生活工作。
我在Google Docs上发布了完整的VS2013项目 https://drive.google.com/file/d/0B05Cvmc8jIzjMW1wS09BSWp3MzA/view?usp=sharing
这是我的纹理绑定代码:
static GLuint gTextures[2];
/* Create textures */
glGenTextures( 2, gTextures );
glBindTexture( GL_TEXTURE_2D, gTextures[ 0 ] );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, gTestTexture0 );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture( GL_TEXTURE_2D, gTextures[ 1 ] );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, gTestTexture1 );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
/* For the next lines, "shader_id" is the value returned from glCreateProgram when I create
the shader. */
glActiveTexture(GL_TEXTURE0);
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, gTextures[0]);
glBindSampler(0, glGetUniformLocation(shader_id, "mytex[0]"));
glActiveTexture(GL_TEXTURE1);
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, gTextures[1]);
glBindSampler(1, glGetUniformLocation(shader_id, "mytex[1]"));
我的片段着色器代码:
#version 330 core
precision mediump float;
in vec3 pass_Color;
in vec2 pass_texcrd0;
in vec2 pass_texcrd1;
uniform sampler2D mytex[ 2 ];
out vec4 outputF;
void main()
{
outputF = vec4(
texture( mytex[ 0 ], pass_texcrd0 ).r * texture( mytex[ 1 ], pass_texcrd1 ).r,
texture( mytex[ 0 ], pass_texcrd0 ).g * texture( mytex[ 1 ], pass_texcrd1 ).g,
texture( mytex[ 0 ], pass_texcrd0 ).b * texture( mytex[ 1 ], pass_texcrd1 ).b,
1.0 );
}
纹理 1 是一个白色正方形,中间有一个灰色正方形,所以我希望输出是我的纹理 0,中间有一些深色阴影。但是,纹理 0 显示为未修改。为了隔离问题,我将片段着色器的 main() 更改为:
outputF = vec4( texture( mytex[ 0 ], pass_texcrd0 ).rgb, 1.0 );
正如预期的那样,这将显示纹理 0。然而,真正的问题是,当我将片段着色器指令更改为仅引用 mytex[ 1 ] 时,输出仍然显示纹理 0。
我已经在两台计算机上尝试过这个,一台带有ATI,一台带有Nvidia。我认为问题可能是ATI计算机仅支持OpenGL 3.2,因此我的着色器不得不使用 #version 150。但是,NVidia支持OpenGL 4.1,所以没有问题。两台机器都支持使用旧客户端调用进行多纹理处理,因此缺乏通用的多纹理支持不是问题所在。
我还尝试使用 glUniform1iv 而不是 glBindSampler() 来设置纹理单位,如下所示:
GLint samplerArrayLoc = glGetUniformLocation(shader_id, "mytex");
const GLint samplers[2] = {0,1}; // we've bound our textures in textures 0 and 1.
glUniform1iv( samplerArrayLoc, 2, samplers );
这也没有任何效果。
我已经在旧的客户端调用(glVertex3d,glTexCoord2d等)中编程很长时间了。我只是在 GLSL 上旋转。所以我只是简单地盯着。我要做的就是在三角形条状图案中渲染一个简单的正方形。我的顶点和纹理坐标数组如下:
float vertices[] =
{
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
-0.5, 0.5, 0.0,
0.5, 0.5, 0.0
};
float tex0[] =
{
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0
};
float tex1[] =
{
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0
};
原始代码中的glBindSampler()
调用不正确:
glBindSampler(0, glGetUniformLocation(shader_id, "mytex[0]"));
此调用的第二个参数必须是采样器对象的名称,而不是统一位置。采样器对象是 OpenGL 3.3 中引入的一项功能,它提供了一种机制来对具有多组采样属性的同一纹理进行采样。要使用glBindSampler()
,作为第二个参数传递的值将是用glGenSamplers()
获得的名称。
除非你真的很好地利用了它们(而且我没有看到基于你发布的内容),否则没有必要在这里涉及采样器对象。
我不确定为什么您的其他尝试没有成功:
GLint samplerArrayLoc = glGetUniformLocation(shader_id, "mytex");
const GLint samplers[2] = {0,1}; // we've bound our textures in textures 0 and 1.
glUniform1iv( samplerArrayLoc, 2, samplers );
由于shader_id
是程序名称(在实际上是程序的变量的名称中使用shader
有些误导),这对我来说看起来不错。确保samplerArrayLoc
作为有效的统一位置返回,即不-1
,并调用glGetError()
以验证没有调用触发错误条件。