简体   繁体   English

执行 glDrawElements 时需要有 glVertexAttribDivisor

[英]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.但是,一旦我删除 glVertexAttribDivisor 行,它就不会呈现任何内容。 Any ideas why this is the case?任何想法为什么会这样?

Note that I'm using glDrawElements not glDrawElementsInstanced.请注意,我使用的是 glDrawElements 而不是 glDrawElementsInstanced。 I thought that glDrawElements is not even looking at glVertexAttribDivisor because I'm drawing single primitive.我认为 glDrawElements 甚至没有查看 glVertexAttribDivisor,因为我正在绘制单个图元。 Could it have something to do with the fact that I bound 2 different VBO's to GL_ARRAY_BUFFER target?这可能与我将 2 个不同的 VBO 绑定到 GL_ARRAY_BUFFER 目标这一事实有关吗? 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.但是然后......只有当适当的 VBO 绑定到 VAO 以及 glBufferData 时,我才调用 glVertexAttribPointer function,所以我不明白。 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.所以我的误解是我认为 glDrawElements 将使用从缓冲区为每个单独顶点提供的相同属性为我绘制给定图元(在我的例子中是四边形)的单个实例。 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.如果没有 glVertexAttribDivisor,只有 4 个顶点中的第一个顶点将获得正确的属性,并且所有 rest 个顶点将获得 0,0,0,0,0...。因此,如果我在这种情况下将缓冲区大小加倍,其中一半将获得数据和其他东西会呈现但垃圾。 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.所以我要从中吸取的教训是,如果没有指定 vertexAttribDivisor,属性将从缓冲区中读取为每个顶点的步幅而不是每个实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么在进行UPDATE时需要明确提交? - Why the need to commit explicitly when doing an UPDATE? 使用glDrawElements时出现黑屏 - getting a black screen when using glDrawElements 在进行POST时,是否需要对表单参数名称进行编码? - Do form parameter names need to be encoded when doing a POST? 在Scikit中进行文本分类时是否需要标准化数据 - Do I need to standardize data when doing text classification in Scikit 为什么在执行外循环时数组的长度必须在它旁边有一个负数 - Why does the length of an array have to have a negative next to it when doing the outer loop 我正在做作业,当输入负数时,此代码需要打印错误消息 - I am doing a homework and this code need to print an error message when a negative number is inputted 我有一个包含字母和数字列表的txt文件,我需要根据数字对它进行排序,我该怎么做? - I have a txt file with a list of letters and numbers, and I need to sort it based on the numbers, how do I go about doing this? 在对大小不同的数据帧进行操作时,是否有设置或方法让 pandas 发出警告或警报? - Is there a setting or way to have pandas warn or alert when doing operations with dataframes that are not the same size? glDrawElements在PyOpenGL中绘制立方体 - glDrawElements to draw a cube in PyOpenGL 需要帮助进行股票数据集分析 - Need help doing analysis on a stock data set
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM