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