GLSL多纹理仅显示纹理0

时间:2014-11-22 01:40:09

标签: opengl glsl multitexturing

在你问之前,是的,我已经阅读了很多教程,在这个论坛和其他论坛上发布了类似的问题等等......我已经尝试了我能找到的每一个建议,但我无法让GLSL 3.3多重纹理在我的生活中工作。

我在https://drive.google.com/file/d/0B05Cvmc8jIzjMW1wS09BSWp3MzA/view?usp=sharing

在Google文档上发布了完整的VS2013项目

这是我的纹理绑定代码:

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
    };

1 个答案:

答案 0 :(得分: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()以验证没有任何调用触发错误情况。