【问题标题】:Shader does not render to window着色器不渲染到窗口
【发布时间】:2021-03-29 23:41:53
【问题描述】:

我有两种测试代码的方法。第一个使用单个 VBO,顶点和纹理坐标交织在一起,在窗口上绘制一个正方形。第二个使用由三个 VBO 组成的数组来定义顶点、纹理坐标和颜色值。

第一种方法成功地在窗口中心渲染了一个黑色方块。第二种方法不渲染任何东西。我开始使用 RenderDoc 进行故障排除,发现在“网格查看器”选项卡下,第一种方法的 glDrawArrays() 调用列出了顶点和纹理坐标。当检查来自第二种方法的 glDrawArrays() 调用时,所有传递的值都是 0。

谁能向我解释为什么会发生这种情况以及如何解决?

第一种方法:

public static void GenDrawQuad() {
        int quadVAO = 0;
        int quadVBO = 0;

        float vertices[] = {
                // Positions         Texcoords
                -0.5f,  0.5f, 0.0f,  -0.5f, 0.5f,
                -0.5f, -0.5f, 0.0f,  -0.5f,-0.5f,
                0.5f,  0.5f, 0.0f,   0.5f, 1.5f,
                0.5f, -0.5f, 0.0f,   0.5f,-0.5f,
        };

        // Gen VAO to contain VBO
        quadVAO = glGenVertexArrays();
        glBindVertexArray(quadVAO);

        // Gen and fill vertex buffer (VBO)
        quadVBO = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
        glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);

        // Bind vertex attributes (position, texcoords)
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 5*Float.BYTES,0); //Positions
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 2, GL_FLOAT, false, 5*Float.BYTES,3*Float.BYTES); //Texcoords

        // Draw quad
        glBindVertexArray(quadVAO);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        glBindVertexArray(0);

        // Delete buffers (VBO and VAO)
        glDeleteBuffers(quadVBO);
        glDeleteVertexArrays(quadVAO);
    }

第一种方法的RenderDoc:

第二种方法:

public static void GenDrawQuadAlt() {
        int quadVAO = 0;
        int[] quadVBO = {0, 0, 0};
        Shader shaderProgram = GetShaderDefault();

        float vertices[] = {
                // Positions
                -0.5f,  0.5f, 0.0f,
                -0.5f, -0.5f, 0.0f,
                 0.5f,  0.5f, 0.0f,
                 0.5f, -0.5f, 0.0f
        };

        float[] texcoords = {
                 0.5f, -0.5f,
                -0.5f, -0.5f,
                 0.5f,  0.5f,
                 0.5f, -0.5f
        };

        float[] colour = {
                255, 109, 154, 255,
                255, 109, 154, 255,
                255, 109, 154, 255,
                255, 109, 154, 255
        };

        // Gen VAO to contain VBO
        quadVAO = glGenVertexArrays();
        glBindVertexArray(quadVAO);

        // Gen and fill vertex buffer (VBO)
        quadVBO[0] = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, quadVBO[0]);
        glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);

        quadVBO[1] = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, quadVBO[1]);
        glBufferData(GL_ARRAY_BUFFER, texcoords, GL_STATIC_DRAW);

        quadVBO[2] = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, quadVBO[2]);
        glBufferData(GL_ARRAY_BUFFER, colour, GL_STATIC_DRAW);

        // Bind vertex attributes (position, texcoords)
        glEnableVertexAttribArray(shaderProgram.getLocs().get(LOC_VERTEX_POSITION.ShaderLocationInt));
        glVertexAttribPointer(shaderProgram.getLocs().get(LOC_VERTEX_POSITION.ShaderLocationInt), 3, GL_FLOAT,
                false, 0,0); //Positions

        glEnableVertexAttribArray(shaderProgram.getLocs().get(LOC_VERTEX_TEXCOORD01.ShaderLocationInt));
        glVertexAttribPointer(shaderProgram.getLocs().get(LOC_VERTEX_TEXCOORD01.ShaderLocationInt), 2, GL_FLOAT,
                false, 0,0); //Texcoords

        glEnableVertexAttribArray(shaderProgram.getLocs().get(LOC_VERTEX_COLOR.ShaderLocationInt));
        glVertexAttribPointer(shaderProgram.getLocs().get(LOC_VERTEX_COLOR.ShaderLocationInt), 4, GL_FLOAT,
                false, 0, 0); //Colours

        // Draw quad
        glUseProgram(shaderProgram.getId());
        glBindVertexArray(quadVAO);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        glBindVertexArray(0);
        glUseProgram(0);

        // Delete buffers (VBO and VAO)
        glDeleteBuffers(quadVBO);
        glDeleteVertexArrays(quadVAO);
    }

RenderDoc 用于第二种方法:

::EDIT::

经过一番修改,我现在有了以下方法,它将值放置在我的着色器的预期位置并给我一个 gl_Position 输出,但不会渲染到屏幕上。

public static void GenDrawQuadAlt() {
        int quadVAO = 0;
        int[] quadVBO = {0, 0, 0, 0};
        Shader shaderProgram = rlglData.getState().getCurrentShader();

        float vertices[] = {
                -0.5f,  0.5f, 0.0f,
                -0.5f, -0.5f, 0.0f,
                0.5f,  0.5f, 0.0f,
                0.5f, -0.5f, 0.0f
        };

        float[] texcoords = {
                0.5f, -0.5f,
                -0.5f, -0.5f,
                0.5f,  0.5f,
                0.5f, -0.5f
        };

        float[] colour = {
                255, 109, 154, 255,
                255, 109, 154, 255,
                255, 109, 154, 255,
                255, 109, 154, 255
        };

        int[] indices = {
                0, 1, 2,
                0, 2, 3
        };

        // Gen VAO to contain VBO
        quadVAO = glGenVertexArrays();
        glBindVertexArray(quadVAO);

        // Gen and fill vertex buffer (VBO)
        quadVBO[0] = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, quadVBO[0]);
        glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
        glVertexAttribPointer(0, 3, GL_FLOAT,
                false, 0,0); //Positions
        glEnableVertexAttribArray(0);

        quadVBO[1] = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, quadVBO[1]);
        glBufferData(GL_ARRAY_BUFFER, texcoords, GL_STATIC_DRAW);
        glVertexAttribPointer(1, 2, GL_FLOAT,
                false, 0,0); //Texcoords
        glEnableVertexAttribArray(1);

        quadVBO[2] = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, quadVBO[2]);
        glBufferData(GL_ARRAY_BUFFER, colour, GL_STATIC_DRAW);
        glVertexAttribPointer(3, 4, GL_FLOAT,
                false, 0, 0); //Colours
        glEnableVertexAttribArray(3);

        quadVBO[3] = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, quadVBO[3]);
        glBufferData(GL_ARRAY_BUFFER, indices, GL_STATIC_DRAW);

        // Draw quad
        glUseProgram(shaderProgram.getId());
        glBindVertexArray(quadVAO);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.length/3);
        glBindVertexArray(0);
        glUseProgram(0);

        // Delete buffers (VBO and VAO)
        glDeleteBuffers(quadVBO);
        glDeleteVertexArrays(quadVAO);
    }

我的顶点着色器:

#version 330                       
in vec3 vertexPosition;            
in vec2 vertexTexCoord;            
in vec4 vertexColor;               
out vec2 fragTexCoord;             
out vec4 fragColor;                
uniform mat4 mvp;                  
void main()                        
{                                  
    fragTexCoord = vertexTexCoord; 
    fragColor = vertexColor;       
    gl_Position = vec4(vertexPosition.x, vertexPosition.y, vertexPosition.z, 1.0); 
}                                  

我的片段着色器:

#version 330       
in vec2 fragTexCoord;              
in vec4 fragColor;                 
out vec4 finalColor;               
uniform sampler2D texture0;        
uniform vec4 colDiffuse;           
void main()                        
{                                  
    vec4 texelColor = texture(texture0, fragTexCoord);   
    finalColor = texelColor*colDiffuse*fragColor;        
}                                  

【问题讨论】:

    标签: java opengl glsl shader lwjgl


    【解决方案1】:

    glVertexAttribPointer 将实际绑定到GL_ARRAY_BUFFER 目标的缓冲区对象与属性相关联。调用glVertexAttribPointer之前必须绑定缓冲区对象:

    glBindBuffer(GL_ARRAY_BUFFER, quadVBO[0]);
    glVertexAttribPointer(shaderProgram.getLocs().get(LOC_VERTEX_POSITION.ShaderLocationInt), 3, GL_FLOAT,
                    false, 0,0); //Positions
    
    glBindBuffer(GL_ARRAY_BUFFER, quadVBO[1]);
    glVertexAttribPointer(shaderProgram.getLocs().get(LOC_VERTEX_TEXCOORD01.ShaderLocationInt), 2, GL_FLOAT,
                    false, 0,0); //Texcoords
    
    glBindBuffer(GL_ARRAY_BUFFER, quadVBO[3]);
    glVertexAttribPointer(shaderProgram.getLocs().get(LOC_VERTEX_COLOR.ShaderLocationInt), 4, GL_FLOAT,
                    false, 0, 0); //Colours
    

    【讨论】:

    • 嗨,我在创建和绑定下一个 VBO 之前以绑定缓冲区并调用 glVertexAttribPointer() 和 glEnableVertexAtribArray() 的形式实现了您的建议。但是,如果您查看我对问题所做的编辑,它仍然没有在屏幕上呈现任何内容。
    【解决方案2】:

    使用glGetUniformLocation() 设置着色器属性后,我发现由于着色器构造函数中的错误,未定义着色器位置值。一旦我纠正了这个错误,我的四边形就被绘制到了屏幕上。

    感谢所有帮助和意见!

    【讨论】:

      【解决方案3】:

      您正在将位置、uv、颜色缓冲到三个不同的缓冲区,这些缓冲区都指向GL_ARRAY_BUFFER 目标。您一次只能与一个目标 + 缓冲区组合进行绘制/交互。你也错过了glVertexAttribpointer

      您需要像使用第一个一样合并您的顶点数据:

            float vertices[] = {
                      // Positions         Texcoords     color
                      -0.5f,  0.5f, 0.0f,  -0.5f, 0.5f,  255, 109, 154, 255, 
      

      然后在这里使用正确的步幅:

      glVertexAttribPointer(0, 3, GL_FLOAT, false, 9*Float.BYTES, 0); // positions
      glVertexAttribPointer(1, 2, GL_FLOAT, false, 9*Float.BYTES, 3*Float.BYTES); // texcoords
      glVertexAttribPointer(2, 4, GL_FLOAT, false, 9*Float.BYTES, 5*Float.BYTES); // color
      

      【讨论】:

      • “您一次只能与一个目标 + 缓冲区组合进行绘制/交互” - 不,这是错误的。
      猜你喜欢
      • 2022-01-24
      • 1970-01-01
      • 1970-01-01
      • 2012-04-29
      • 1970-01-01
      • 2012-08-14
      • 2016-09-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多