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

dav*_*one 21 opengl glsl texture-mapping texture2d opengl-2.0

我使用freeglut,GLEW 和魔鬼,以呈现纹理的茶壶使用顶点和片段着色器.这在Ubuntu 14.04上的OpenGL 2.0和GLSL 1.2中都运行良好.

现在,我想将凹凸贴图应用于茶壶.我的讲师显然不会酿造他自己的茶,所以不知道他们应该是顺利的.无论如何,我找到了一个关于老式凹凸贴图的漂亮教程,其中包括一个片段着色器,它开始于:

uniform sampler2D DecalTex; //The texture
uniform sampler2D BumpTex; //The bump-map 
Run Code Online (Sandbox Code Playgroud)

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

以前我

//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);
Run Code Online (Sandbox Code Playgroud)

所以现在我

//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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

gla*_*ert 35

真的很简单.您只需将采样器绑定到某个纹理单元即可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)
Run Code Online (Sandbox Code Playgroud)

在您的初始化代码中:

// 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);
Run Code Online (Sandbox Code Playgroud)

好的,着色器制服设置,现在我们渲染.为此,您需要通常的glBindTexture加号glActiveTexture:

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.
Run Code Online (Sandbox Code Playgroud)

在着色器中,您将使用纹理采样器,就像您已经做的那样:

vec4 a = texture2D(DecalTex, tc);
vec4 b = texture2D(BumpTex,  tc);
Run Code Online (Sandbox Code Playgroud)

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

  • 对于任何想知道的人来说,`GL_TEXTURE0 + 1 == GL_TEXTURE1` (5认同)
  • 优秀!我最主要的困惑是glGetUniformLocation / glUseProgram / glUniform1i的顺序-如http://stackoverflow.com/a/12065077/236081中所述,我必须在最终的glBindTexture之后执行“ glActiveTexture(GL_TEXTURE0 + 0);”。为它的工作-并感谢khronos链接 (3认同)