[英]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.