-1

在你问之前,是的,我已经阅读了很多教程,在这个论坛和其他论坛上发布的类似问题等等......我已经尝试了我能找到的每一个建议,但我无法让 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
    };
4

1 回答 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作为有效的统一位置返回,即 not -1,并调用glGetError()以验证没有任何调用触发错误条件。

于 2014-11-22T03:20:41.287 回答