簡體   English   中英

執行 glDrawElements 時需要有 glVertexAttribDivisor

[英]need to have glVertexAttribDivisor when doing glDrawElements

我在做我的小項目,這里有一些代碼:

四邊形定義:

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

着色器定義:

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

以下是綁定:

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()

最終綁定和繪圖:

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)

我很困惑,因為上面的代碼有效並且一切都正確呈現。 但是,一旦我刪除 glVertexAttribDivisor 行,它就不會呈現任何內容。 任何想法為什么會這樣?

請注意,我使用的是 glDrawElements 而不是 glDrawElementsInstanced。 我認為 glDrawElements 甚至沒有查看 glVertexAttribDivisor,因為我正在繪制單個圖元。 這可能與我將 2 個不同的 VBO 綁定到 GL_ARRAY_BUFFER 目標這一事實有關嗎? 但是然后......只有當適當的 VBO 綁定到 VAO 以及 glBufferData 時,我才調用 glVertexAttribPointer function,所以我不明白。 請幫助我更好地理解這一點。

所以我的誤解是我認為 glDrawElements 將使用從緩沖區為每個單獨頂點提供的相同屬性為我繪制給定圖元(在我的例子中是四邊形)的單個實例。 事實並非如此!

如果沒有 glVertexAttribDivisor,只有 4 個頂點中的第一個頂點將獲得正確的屬性,並且所有 rest 個頂點將獲得 0,0,0,0,0...。因此,如果我在這種情況下將緩沖區大小加倍,其中一半將獲得數據和其他東西會呈現但垃圾。 使用給定緩沖區的四倍大小,一切都按應有的方式呈現。

所以我要從中吸取的教訓是,如果沒有指定 vertexAttribDivisor,屬性將從緩沖區中讀取為每個頂點的步幅而不是每個實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM