我在我的小项目,这里是一些代码:
四元组定义:
#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函数。所以我不明白请你帮我弄明白。
1条答案
按热度按时间atmip9wb1#
所以我的误解是我以为glDrawElements会为我绘制一个给定图元的单个示例(在我的例子中是四边形),使用的属性与从buffer为每个单独的顶点提供的属性相同。
如果没有glVertexAttribDivisor,只有4个顶点中的第一个会得到正确的属性,其余的顶点会得到0,0,0,0,0 ....所以如果我在这种情况下将缓冲区大小增加一倍,它们中的一半会得到数据,有些会呈现垃圾。
我从中得到的教训是,**如果没有指定vertexAttribDivisor,属性将作为每个顶点的步幅从缓冲区读取,**而不是每个整个示例。