如何将多个纹理传递到单个着色器?

时间:2014-08-11 21:12:40

标签: opengl glsl texture-mapping texture2d opengl-2.0

我正在使用freeglut,GLEW and DevILrender a textured teapot使用顶点和片段着色器。这在Ubuntu 14.04上的OpenGL 2.0和GLSL 1.2中都运行良好。

现在,我想将凹凸贴图应用于茶壶。我的讲师显然没有自己酿造茶,所以不知道他们应该是smooth。无论如何,我发现a nice-looking tutorial on old-school bump mapping包含一个开始的片段着色器:

uniform sampler2D DecalTex; //The texture
uniform sampler2D BumpTex; //The bump-map 

他们没有提到的是如何首先将两个纹理传递到着色器。

以前我

//OpenGL cpp file
glBindTexture(GL_TEXTURE_2D, textureHandle);

//Vertex shader
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

//Fragment shader
gl_FragColor = color * texture2D(DecalTex,gl_TexCoord[0].xy);

所以现在我

//OpenGL cpp file
glBindTexture(GL_TEXTURE_2D, textureHandle);
glBindTexture(GL_TEXTURE_2D, bumpHandle);

//Vertex shader
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;

//Fragment shader
gl_FragColor = color * texture2D(BumpTex,gl_TexCoord[0].xy);
//no bump logic yet, just testing I can use texture 1 instead of texture 0

但这不起作用。纹理完全消失(茶壶是白色的)。我已经尝试了GL_TEXTURE_2D_ARRAY,glActiveTexture以及其他一些可能看似但毫无结果的选项。

在筛选出通常的OpenGL和新旧GLSL的混合包之后,我得出的结论是我可能需要glGetUniformLocation。我究竟如何在OpenGL cpp文件中使用 将已经填充的纹理句柄传递给片段着色器?

(这是作业,所以请用最少的代码片段回答(如果有的话)。谢谢!)

如果不这样做,有没有人有茶舒适的网格?

2 个答案:

答案 0 :(得分:33)

这很简单,真的。您所需要的只是将采样器绑定到具有glUniform1i的纹理单元。因此,对于您的代码示例,假设有两个统一的采样器:

uniform sampler2D DecalTex;  // The texture  (we'll bind to texture unit 0)
uniform sampler2D BumpTex;   // The bump-map (we'll bind to texture unit 1)

在初始化代码中:

// Get the uniform variables location. You've probably already done that before...
decalTexLocation = glGetUniformLocation(shader_program, "DecalTex");
bumpTexLocation  = glGetUniformLocation(shader_program, "BumpTex");

// Then bind the uniform samplers to texture units:
glUseProgram(shader_program);
glUniform1i(decalTexLocation, 0);
glUniform1i(bumpTexLocation,  1);

好的,着色器制服设置,现在我们渲染。为此,您需要通常的glBindTextureglActiveTexture

glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0
glBindTexture(GL_TEXTURE_2D, decalTexHandle);

glActiveTexture(GL_TEXTURE0 + 1); // Texture unit 1
glBindTexture(GL_TEXTURE_2D, bumpHandle);

// Done! Now you render normally.

在着色器中,您将像使用纹理采样器一样使用纹理采样器:

vec4 a = texture2D(DecalTex, tc);
vec4 b = texture2D(BumpTex,  tc);

注意:对于像凹凸贴图这样的技术,您只需要一组纹理坐标,因为纹理是相同的,只包含不同的数据。所以你应该将纹理坐标传递为vertex attribute

答案 1 :(得分:-1)

而不是使用:

glUniform1i(decalTexLocation, 0);
glUniform1i(bumpTexLocation,  1);
在你的代码中

你可以:

layout(binding=0) uniform sampler2D DecalTex;  
// The texture  (we'll bind to texture unit 0)
layout(binding=1)uniform sampler2D BumpTex;   
// The bump-map (we'll bind to texture unit 1)
着色器中的

。这也意味着您不必查询该位置。