简体   繁体   中英

need to have glVertexAttribDivisor when doing glDrawElements

Im working on my little project and here is some code:

Quad definitions:

#Geometry definitions   XYZ             UV
quad_vertices = [-0.5, -0.5, 0.0,   0.0, 0.0,
                  0.5, -0.5, 0.0,   1.0, 0.0,
                  0.5,  0.5, 0.0,   1.0, 1.0,
                 -0.5,  0.5, 0.0,   0.0, 1.0]

quad_indices = [0, 1, 2, 2, 3, 0]

quad_vertices = np.array(quad_vertices, dtype=np.float32)
quad_indices = np.array(quad_indices, dtype=np.uint32)

Shader definition:

vertex_src2 = """
# version 330 core

layout(location = 0) in vec3 a_position;
layout(location = 1) in vec2 a_texture_uv;
layout(location = 2) in vec4 a_color;
layout(location = 3) in vec3 translation;
layout(location = 4) in vec3 scale;
layout(location = 5) in vec2 a_tex_index;
layout(location = 6) in vec4 a_effect_params; //currently not used

uniform mat4 projection;
uniform mat4 view;

out vec4 v_color;
out vec2 v_texture;
out float z_texture0;
out float z_texture1;
out vec4 effect_params;

mat4 BuildTranslation(vec3 delta)
{
    return mat4(1.0, 0.0, 0.0, 0.0,
                0.0, 1.0, 0.0, 0.0,
                0.0, 0.0, 1.0, 0.0,
                delta, 1.0);
}

mat4 BuildRotation(vec3 delta){
    return mat4(cos(radians(delta[2])), -sin(radians(delta[2])),  0.0, 0.0,
                sin(radians(delta[2])),  cos(radians(delta[2])),  0.0, 0.0,
                0.0,         0.0,         1.0, 0.0,
                0.0,         0.0,         0.0, 1.0);
}

mat4 BuildScale(vec3 delta){
    return mat4(delta[0], 0.0, 0.0, 0.0,
                0.0, delta[1], 0.0, 0.0,
                0.0, 0.0, delta[2], 0.0,
                0.0, 0.0, 0.0, 1.0);
}

void main()
{
    mat4 model = BuildTranslation(translation) * BuildScale(scale);
    gl_Position = projection * view * model * vec4(a_position, 1.0f);
    v_texture = a_texture_uv;
    v_color = a_color;
    z_texture0 = a_tex_index.x;
    z_texture1 = a_tex_index.y;
    effect_params = vec4(0);
}
"""

#Fragment shader definition
fragment_src2 = """
# version 330 core

in vec4 v_color;
in vec2 v_texture;
in float z_texture0;
in float z_texture1;
in vec4 effect_params;

out vec4 out_color;

uniform int switcher;
uniform sampler2DArray s_texture;

void main()
{
    if (switcher == 0){
        float effectNo = effect_params[3];
        vec4 texel = texture(s_texture, vec3(v_texture, z_texture0));
       
        texel.a = texel.a * v_color.a;
        if (texel.a < 0.05){
            discard;
        }
        out_color = texel;
    }
}
"""

Here are the bindings:

def bind_buffer_data(self):
        glBindVertexArray(self.VAO)
        glBindBuffer(GL_ARRAY_BUFFER, self.VBO[0])
        glBufferData(GL_ARRAY_BUFFER, quad_vertices.nbytes, quad_vertices, GL_STATIC_DRAW)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.EBO)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, quad_indices.nbytes, quad_indices, GL_STATIC_DRAW)

        for i in range(6):
            glEnableVertexAttribArray(i)
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, ctypes.c_void_p(0))
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, ctypes.c_void_p(12))
        glBindBuffer(GL_ARRAY_BUFFER, self.VBO[1]) // This is bound for later loading of buffer data during draw_object()

Final bindings and drawing:

def draw_object(self, depth, alpha=1.0, switcher=0):
        self.color[3] = alpha
        buffer_data = np.array(
            [self.color[0], self.color[1], self.color[2], self.color[3], 
             self.pos_x, self.pos_y, depth, 
             self.scale[0], self.scale[1], self.scale[2], 
             0, 0], 
             dtype=np.float32)

        glBindVertexArray(self.VAO)
        glBindTexture(GL_TEXTURE_2D_ARRAY, self.get_current_texture())

        glBufferData(GL_ARRAY_BUFFER, buffer_data.nbytes, buffer_data, GL_DYNAMIC_DRAW)
        
        glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 48, ctypes.c_void_p(0))
        glVertexAttribDivisor(2, 1) #Cannot delete that?
        
        glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 48, ctypes.c_void_p(16))
        glVertexAttribDivisor(3, 1) #Cannot delete that?
        
        glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 48, ctypes.c_void_p(28))
        glVertexAttribDivisor(4, 1) #Cannot delete that?
        
        glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, 48, ctypes.c_void_p(40))
        glVertexAttribDivisor(5, 1) #Cannot delete that?

        glUniform1i(shader.switcher_loc2, switcher)
        glDrawElements(GL_TRIANGLES, len(quad_indices), GL_UNSIGNED_INT, None)

I'm very puzzled because above code works and everything renders properly. However as soon as I remove glVertexAttribDivisor lines it doesn't render anything. Any ideas why this is the case?

Note that I'm using glDrawElements not glDrawElementsInstanced. I thought that glDrawElements is not even looking at glVertexAttribDivisor because I'm drawing single primitive. Could it have something to do with the fact that I bound 2 different VBO's to GL_ARRAY_BUFFER target? But then... I'm calling glVertexAttribPointer function only when proper VBO is bound to the VAO as well as glBufferData, so I don't understand. Please help me understand this better.

So the misconception I had was that I thought that glDrawElements is going to draw me a single instance of a given primitive (quad in my case) using same attributes it was given from buffer for each individual vertex. That is not the case!

Without glVertexAttribDivisor only the first vertex out of 4 will get correct attributes and all the rest of them will get 0,0,0,0,0.... So if I double the buffer size in this case, half of them will get the data and something will render but garbage. With quadruple size of the given buffer everything renders as it should.

So my lesson to take away from this is that without vertexAttribDivisor specified, the attributes are going to be read from buffer as stride per vertex not per whole instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM