Search code examples
glslshadervertex-shaderopengl-3vertex

OpenGL vertex shader processing


I'm pretty new to 3D programming. I'm trying to learn OpenGL from this site. During the reading I couldn't really understand how the layout (location = 0) line really operates. I've tried to search for other explanation online both in the OpenGL wiki and in other sites, and I've managed to find this site from which I understood a little more.

So if I am correct the vertex shader takes some inputs and generates some outputs. The input of the shader are called vertex attributes and each one of them as an index location called attribute index. Now I expect that if the shader takes as input a single vertex and its attributes, it has to run multiple times, one for each vertex of the object I'm trying to render. Is it correct what I wrote up until this point?

Now, what I didn't manage to understand is how layout (location = 0) really works. My assumption is that this intruction needs to tell the shader from where location in memory to pick the first index attribute. Thus each time the shader re-runs (if it actually re-runs), the location should move by one unit, like in a normal for loop. Is this interpretation correct? And, please, can anyone actually explain me, in an organic way, how the vertex shader operates?

P.S. Thank you in advance for your time and excuse my poor English: I'm still practising it!

Edit

This is the code. Following the first guide I linked I created an array of vertices:

float vertices[] {

   -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    0.0f,  0.5f, 0.0f

};

then I created a vertex buffer object:

unsigned int VBO;
glGenBuffer(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);

I added the data to the VBO:

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

while the vertex shader reads:

#version 330 core
layout (location = 0) in vec3 aPos:

void main() {
    gl_Position(aPos.x, aPos.y, aPos.z, 1.0f);
}

Solution

  • You need to look at both sides of this. You bind a buffer containing all of your data. Say position and color.

    layout(location = 0) in vec3 position;
    layout(location = 1) in vec3 color;
    

    Now in the program, I can use these vectors without specifying the index of the vertex I am processing because we had to tell GL how to buffer the data.

    We do that when we bind buffers to the program.

    Lets say we want to create a triangle. It has 3 vertexes, each vertex has two attributes: color and position. We create a vertex shader that processes each vertex, in that program it is implied that each vertex has a color and position. You don't care about the index in the array it is (for now).

    The program will take vertex i, v_i and process it. How it populates position and vector depend on how you bind the data. I could have two arrays,

    positionData = [x0, y0, z0, x1, ... z3];
    colorData = [r0, g0, b0, r1, ... b3];
    

    So I would buffer this data, then I would bind that buffer to the program at the attribute location and specify how it is read. Eg. bind the positionBuffer to attribute location 0, read it in strides of three with no offset.

    The same with the color data, but with location 1.

    Alternatively I could do.

    posColData = [ x0, y0, z0, r0, g0, b0, x1, y1, ... b3];
    

    Then I would create posColBuffer and bind it to the 0th attribute, with a stride of 6. I would also bind the posColBuffer to the 1st attribute with a stride of 6 and an offset of 3.

    The code you are using does this here.

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);  ;
    

    They utilize the layout clause by just saying 0 since they know the location.