36

我正在使用 freeglut、GLEW和 DevIL使用顶点和片段着色器来渲染纹理茶壶。这在 Ubuntu 14.04 上的 OpenGL 2.0 和 GLSL 1.2 中一切正常。

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

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 文件中使用它来将已经填充的纹理句柄传递给片段着色器?

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

如果做不到这一点,有人有茶舒适网吗?

4

2 回答 2

66

这很简单,真的。您所需要的只是将采样器绑定到某个纹理单元,使用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);

好的,着色器制服设置,现在我们渲染。为此,您将需要通常的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.

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

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

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

于 2014-08-11T21:49:04.947 回答
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)

在你的着色器中。这也意味着您不必查询位置。

于 2017-06-26T06:33:24.260 回答