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