0
\$\begingroup\$

I've got two methods of test code. The first uses a single VBO with the vertices and texture coordinates interwoven to draw a square to the window. The second uses an array of three VBOs to define the vertices, texture coordinates, and colour values.

The first method successfully renders a black square to the centre of the window. The second method does not render anything. I began troubleshooting with RenderDoc and found that under the "Mesh Viewer" tab the glDrawArrays() call from the first method lists the vertices and texture coordinates. When Examining the glDrawArrays() call from the second method all values passed are 0.

Can anyone explain to me why this is happening and how it can be resolved?

First Method:

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 for the first method: RenderDoc for first method:

Second Method:

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 for the second method: RenderDoc for the second method

::EDIT::

After a bit of tinkering I now have the following method which places the values in the expected locations for my shader and gives me a gl_Position output, but does not render to the screen.

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);
    }

My vertex shader:

#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); 
}                                  

My fragment shader:

#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;        
}                                  
\$\endgroup\$
1
\$\begingroup\$

glVertexAttribPointer sources data from the currently bound GL_ARRAY_BUFFER.

What this means is that if you're drawing using 3 buffers, you must ensure that the correct buffer is bound for each glVertexAttribPointer call.

So instead of:

    // 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

You should do:

    // Gen and fill vertex buffer (VBO)
    quadVBO[0] = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, quadVBO[0]);
    glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(shaderProgram.getLocs().get(LOC_VERTEX_POSITION.ShaderLocationInt), 3, GL_FLOAT,
            false, 0,0); //Positions

    quadVBO[1] = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, quadVBO[1]);
    glBufferData(GL_ARRAY_BUFFER, texcoords, GL_STATIC_DRAW);
    glVertexAttribPointer(shaderProgram.getLocs().get(LOC_VERTEX_TEXCOORD01.ShaderLocationInt), 2, GL_FLOAT,
            false, 0,0); //Texcoords

    quadVBO[2] = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, quadVBO[2]);
    glBufferData(GL_ARRAY_BUFFER, colour, GL_STATIC_DRAW);
    glVertexAttribPointer(shaderProgram.getLocs().get(LOC_VERTEX_COLOR.ShaderLocationInt), 4, GL_FLOAT,
            false, 0, 0); //Colours

    // Bind vertex attributes (position, texcoords)
    glEnableVertexAttribArray(shaderProgram.getLocs().get(LOC_VERTEX_POSITION.ShaderLocationInt));
    glEnableVertexAttribArray(shaderProgram.getLocs().get(LOC_VERTEX_TEXCOORD01.ShaderLocationInt));
    glEnableVertexAttribArray(shaderProgram.getLocs().get(LOC_VERTEX_COLOR.ShaderLocationInt));

In the former case (your original code), for each glVertexAttribPointer call, the currently bound GL_ARRAY_BUFFER is quadVBO[2] so you're telling OpenGL that quadVBO[2] is the data source for each.

In the latter case, the buffer that you actually want to use for each is bound before each call, and everything will work as you want.

Note that it's valid to call glEnableVertexAttribArray after your other calls here.

\$\endgroup\$
3
  • \$\begingroup\$ Hi, I implemented your changes into my code, but I'm still not getting anything rendered to the screen. The mesh viewer still reads 0 for all properties like I included in the original post \$\endgroup\$ – CreedVI Mar 29 at 17:21
  • \$\begingroup\$ @CreedVI - could you update your question with your new code please? There's something else wrong if this is not working, but we'd need to see the next revision of the code in order to help you determine what it is. \$\endgroup\$ – Maximus Minimus Mar 30 at 8:44
  • \$\begingroup\$ Please see the edit I made to the question. Thank you for your help thus far \$\endgroup\$ – CreedVI Mar 31 at 2:48
0
\$\begingroup\$

After using glGetUniformLocation() to set the shader properties I discovered the shader location values were not being defined due to an error in my shader constructor. Once I rectified that error my quad was drawn to the screen.

Thanks for all the help and input!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.