OpenGL:如何将多个纹理传递给具有一个变量的着色器?

Posted

技术标签:

【中文标题】OpenGL:如何将多个纹理传递给具有一个变量的着色器?【英文标题】:OpenGL : How can I pass multiple texture to a shader with one variable? 【发布时间】:2020-09-25 02:41:50 【问题描述】:

我根据这段代码 (https://github.com/Bly7/OBJ-Loader) 从 Obj 文件中加载了材质和纹理信息。现在我想加载 Sponza 并渲染它。但是,有10个或更多的纹理,即使都传递给着色器,也需要对应适当的顶点。查看从 Obj 文件加载的结果,纹理被分配到每个部分。

示例。

Mesh 0 : Pillar
position0(x, y, z), position1(x, y, z), uv0(x, y) ... 
diffuse texture : tex0.png

Mesh 1 : Wall
position0(x, y, z), position1(x, y, z), uv0(x, y) ... 
diffuse texture : tex1.png
.
. 
.

纹理保存为一个数组,每个纹理都有一个对应的网格索引。在我看来,将顶点信息传递给着色器时,如果将其除以网格数并同时传递纹理,则效果很好。但是,我不确定这个想法是否正确,我尝试了几种方法,但都不起作用。

这是当前的简单代码。

main.cpp :
do 
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture[i]);  // texture[] : Array of textures loaded from obj file.
    glUniform1i(glGetUniformLocation(shaderID, "myTex"), 0);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertex_position);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, texCoord);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);    

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element);
    glDrawElements(GL_TRIANGLES, element_indices.size(), GL_UNSIGNED_INT, (void*)0);

 while(glfwWindowShouldClose(window) == 0);

Fragment shader :
layout(location = 0) out vec4 out_color;
// from vertex shader
in vec2 texCoord; 

uniform sampler2D myTex;

void main() 
    out_color = texture(myTex, texCoord);

我想对应上面代码中加载了“i”的网格索引。如果我的想法是错误的或者是否有其他方法,请告诉我。

【问题讨论】:

您必须用tex0.png 渲染Mesh 0,用Mesh 1 渲染tex1.png 等等。为此,您需要加载所有纹理并绑定相应的纹理。绘制缓冲区之前相应网格的纹理 ID。还有一个选项可以为一个网格绑定多个纹理,但恕我直言,这不是您打算做的。看看Learn OpenGL - Textures这是如何详细完成的。 我建议你看看Model - LearnOpenGL。这应该有你的答案。 @Scheff 再次查看您的链接给了我一些关于如何继续的提示。谢谢。 【参考方案1】:

由于您的模型每个网格只有一个纹理,我可以建议使用以下简单代码:

do 
    glActiveTexture(GL_TEXTURE0);
    glUniform1i(glGetUniformLocation(shaderID, "myTex"), 0);
    
    for (unsigned int i = 0; i < mesh_count; i++) 
        glcall(glBindTexture(type, texture[i]));
        
        // Bind vertex and index (or element) buffer and setup vertex attribute pointers
        
        // Draw mesh
    
 while (window_open);

代码很不言自明。它首先激活纹理槽 0,然后为每个网格绑定纹理、顶点缓冲区、索引或元素缓冲区,并为绘制网格做任何准备。然后它发出draw call。

请注意,这是非常基本的示例。大多数模型使用这段代码看起来很奇怪。我会向 LearnOpenGL 的 this tutorial 推荐,它可以更广泛但更简单地解释这一点。

【讨论】:

我通过将一个包含每个网格索引的数组传递给 glDrawElements 来解决它。谢谢大家一起思考。

以上是关于OpenGL:如何将多个纹理传递给具有一个变量的着色器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在OpenGL中处理纹理动画? [关闭]

将灰度 OpenCV 图像传递给 OpenGL 纹理

如何向我的 openGL 程序添加多个纹理?

通过opengl中的纹理传递数组数据

使用 GStreamer 和 NVENC 编码 OpenGL 纹理?

带有 FBO 的 OpenGL 阴影映射 - 多个拖尾绘制