代码之家  ›  专栏  ›  技术社区  ›  lofidevops

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

  •  38
  • lofidevops  · 技术社区  · 10 年前

    我用的是免费的,GLEW and DevIL render a textured teapot 使用顶点和片段着色器。这在Ubuntu 14.04上的OpenGL2.0和GLSL1.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 回复  |  直到 10 年前
        1
  •  72
  •   glampert    10 年前

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

    注意:对于凹凸贴图等技术,只需要一组纹理坐标,因为纹理是相同的,只包含不同的数据。因此,您可能应该将纹理坐标作为 vertex attribute .

        2
  •  4
  •   Felix Dhumes merak    6 年前

    而不是使用:

    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)
    

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