PyOpenGL 没有绘制大 VAO
PyOpenGL not drawing big VAO
我想渲染一个由许多立方体组成的大场景。我的第一个想法是创建一个立方体 VBO,然后使用统一模型矩阵对其进行多次绘制以对其进行转换。这很慢,因为我每帧调用 glDrawArrays
很多次。
所以我决定改用一个巨大的 VBO,每个立方体顶点和一个额外的平移向量。基本上,我将旧的通用立方体 VBO 加上平移矢量,并将该列表附加到我要绘制的每个立方体的 VBO 列表中。然后我绑定一个 VAO 并绘制它。我还更改了顶点着色器,使其接受该平移向量作为顶点属性,并在着色器内生成模型矩阵。
现在,这 return 没有任何错误,这很好,但它实际上并没有绘制任何东西,这不是很好,尽管这个过程与我之前所做的非常相似.
这是一些代码:
Whopper VBO 创建者:
class render:
def __init__(self, coords_list):
self.render_list = []
for i in coords_list:
self.render_list.append([
# Cube model Texture Translation
0.0, 0.0, 0.0, 1.0, 1.0, i[0], i[1], i[2],
1.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2],
1.0, 1.0, 0.0, 0.0, 0.0, i[0], i[1], i[2],
1.0, 1.0, 0.0, 0.0, 0.0, i[0], i[1], i[2],
0.0, 1.0, 0.0, 1.0, 0.0, i[0], i[1], i[2],
0.0, 0.0, 0.0, 1.0, 1.0, i[0], i[1], i[2],
0.0, 0.0, 1.0, 1.0, 1.0, i[0], i[1], i[2],
1.0, 0.0, 1.0, 0.0, 1.0, i[0], i[1], i[2],
1.0, 1.0, 1.0, 0.0, 0.0, i[0], i[1], i[2],
1.0, 1.0, 1.0, 0.0, 0.0, i[0], i[1], i[2],
0.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2],
0.0, 0.0, 1.0, 1.0, 1.0, i[0], i[1], i[2],
0.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2],
0.0, 1.0, 0.0, 0.0, 0.0, i[0], i[1], i[2],
0.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2],
0.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2],
0.0, 0.0, 1.0, 1.0, 1.0, i[0], i[1], i[2],
0.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2],
1.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2],
1.0, 1.0, 0.0, 0.0, 0.0, i[0], i[1], i[2],
1.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2],
1.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2],
1.0, 0.0, 1.0, 1.0, 1.0, i[0], i[1], i[2],
1.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2],
0.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2],
1.0, 0.0, 0.0, 1.0, 1.0, i[0], i[1], i[2],
1.0, 0.0, 1.0, 1.0, 0.0, i[0], i[1], i[2],
1.0, 0.0, 1.0, 1.0, 0.0, i[0], i[1], i[2],
0.0, 0.0, 1.0, 0.0, 0.0, i[0], i[1], i[2],
0.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2],
0.0, 1.0, 0.0, 0.0, 1.0, i[0], i[1], i[2],
1.0, 1.0, 0.0, 1.0, 1.0, i[0], i[1], i[2],
1.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2],
1.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2],
0.0, 1.0, 1.0, 0.0, 0.0, i[0], i[1], i[2],
0.0, 1.0, 0.0, 0.0, 1.0, i[0], i[1], i[2],
])
print('Cube added!')
def create_buffers(self):
render_vbo, self.render_vao = glGenBuffers(1), glGenVertexArrays(1)
glBindVertexArray(self.render_vao)
glBindBuffer(GL_ARRAY_BUFFER, render_vbo)
glBufferData(GL_ARRAY_BUFFER, np.array(self.render_list), GL_STATIC_DRAW)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(12))
glEnableVertexAttribArray(1)
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(20))
glEnableVertexAttribArray(2)
def draw_buffer(self, program, texture):
program.use()
glBindTexture(GL_TEXTURE_2D, texture)
glBindVertexArray(self.render_vao)
glDrawArrays(GL_TRIANGLES, 0, int(len(self.render_list)/8))
初始化和渲染循环:
def main():
global delta_time, last_frame
test_chunk = chunk.chunk((0,0,0)) #Creates a 16x16x16 cube of cubes
test_chunk.fill_layers(0, 16, 1) #Works fine
window = utilities.window()
camera.setup_window(window)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
shader_program = utilities.shader(vertex_source_3d, fragment_source_3d, '330')
shader_program.compile()
#Check which cubes are exposed and should be rendered
#Works fine
exposed_list = [i for i, blocktype in np.ndenumerate(test_chunk.data) if test_chunk.return_if_exposed(i) == True and blocktype != 0]
shader_program.use()
shader_program.set_int('texture0', 0)
camera_direction = glm.vec3()
yaw = -90.0
second_counter = 0
frame_counter = 0
render = cube.render(exposed_list)
render.create_buffers()
while not window.check_if_closed():
current_frame = glfw.get_time()
delta_time = current_frame - last_frame
last_frame = current_frame
second_counter += delta_time
frame_counter += 1
window.refresh(0)
camera.process_input(window, delta_time)
camera.testing_commands(window)
glActiveTexture(GL_TEXTURE0)
shader_program.use()
pos, looking, up = camera.return_vectors()
view = glm.lookAt(pos, looking, up)
projection = glm.perspective(glm.radians(45), window.size[0]/window.size[1], 0.1, 100)
shader_program.set_mat4('view', glm.value_ptr(view))
shader_program.set_mat4('projection', glm.value_ptr(projection))
render.draw_buffer(shader_program, cobble_tex_ID)
glBindVertexArray(0)
if second_counter >= 1:
print(frame_counter)
second_counter, frame_counter = 0, 0
window.refresh(1)
window.close()
if __name__ == '__main__':
main()
顶点着色器:
#version %s core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
layout (location = 2) in vec3 cube_coord;
out vec2 TexCoord;
uniform mat4 view;
uniform mat4 projection;
mat4 model = mat4(1.0);
void main() {
model[0].w = cube_coord.x;
model[1].w = cube_coord.y;
model[2].w = cube_coord.z;
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = aTexCoord;
}
片段着色器:
version %s core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D texture0;
void main()
{
FragColor = texture(texture0, TexCoord);
}
将翻译分配给模型矩阵是错误的。 glsl 矩阵按列主要顺序存储。翻译是第 4 列。典型的模型矩阵如下所示:
mat4 m44 = mat4(
vec4( Xx, Xy, Xz, 0.0),
vec4( Yx, Xy, Yz, 0.0),
vec4( Zx Zy Zz, 0.0),
vec4( Tx, Ty, Tz, 1.0) );
您必须更改模型矩阵初始化:
mat4 model = mat4(1.0);
void main() {
model[3] = vec4(cube_coord.xyz, 1.0);
// [...]
}
此外,您必须为 numpy.array
(numpy.float32
) 指定数据类型:
glBufferData(GL_ARRAY_BUFFER, np.array(self.render_list), GL_STATIC_DRAW)
glBufferData(GL_ARRAY_BUFFER, np.array(self.render_list, np.float32), GL_STATIC_DRAW)
顶点数组是二维的,因此len(self.render_list)/8
不是顶点数:
glDrawArrays(GL_TRIANGLES, 0, int(len(self.render_list)/8))
no_of_verices = len(self.render_list) * 36
glDrawArrays(GL_TRIANGLES, 0, no_of_verices)
分别
no_of_verices = len(self.render_list) * len(self.render_list[0]) // 8
glDrawArrays(GL_TRIANGLES, 0, no_of_verices)
我想渲染一个由许多立方体组成的大场景。我的第一个想法是创建一个立方体 VBO,然后使用统一模型矩阵对其进行多次绘制以对其进行转换。这很慢,因为我每帧调用 glDrawArrays
很多次。
所以我决定改用一个巨大的 VBO,每个立方体顶点和一个额外的平移向量。基本上,我将旧的通用立方体 VBO 加上平移矢量,并将该列表附加到我要绘制的每个立方体的 VBO 列表中。然后我绑定一个 VAO 并绘制它。我还更改了顶点着色器,使其接受该平移向量作为顶点属性,并在着色器内生成模型矩阵。
现在,这 return 没有任何错误,这很好,但它实际上并没有绘制任何东西,这不是很好,尽管这个过程与我之前所做的非常相似.
这是一些代码:
Whopper VBO 创建者:
class render: def __init__(self, coords_list): self.render_list = [] for i in coords_list: self.render_list.append([ # Cube model Texture Translation 0.0, 0.0, 0.0, 1.0, 1.0, i[0], i[1], i[2], 1.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2], 1.0, 1.0, 0.0, 0.0, 0.0, i[0], i[1], i[2], 1.0, 1.0, 0.0, 0.0, 0.0, i[0], i[1], i[2], 0.0, 1.0, 0.0, 1.0, 0.0, i[0], i[1], i[2], 0.0, 0.0, 0.0, 1.0, 1.0, i[0], i[1], i[2], 0.0, 0.0, 1.0, 1.0, 1.0, i[0], i[1], i[2], 1.0, 0.0, 1.0, 0.0, 1.0, i[0], i[1], i[2], 1.0, 1.0, 1.0, 0.0, 0.0, i[0], i[1], i[2], 1.0, 1.0, 1.0, 0.0, 0.0, i[0], i[1], i[2], 0.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2], 0.0, 0.0, 1.0, 1.0, 1.0, i[0], i[1], i[2], 0.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2], 0.0, 1.0, 0.0, 0.0, 0.0, i[0], i[1], i[2], 0.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2], 0.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2], 0.0, 0.0, 1.0, 1.0, 1.0, i[0], i[1], i[2], 0.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2], 1.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2], 1.0, 1.0, 0.0, 0.0, 0.0, i[0], i[1], i[2], 1.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2], 1.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2], 1.0, 0.0, 1.0, 1.0, 1.0, i[0], i[1], i[2], 1.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2], 0.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2], 1.0, 0.0, 0.0, 1.0, 1.0, i[0], i[1], i[2], 1.0, 0.0, 1.0, 1.0, 0.0, i[0], i[1], i[2], 1.0, 0.0, 1.0, 1.0, 0.0, i[0], i[1], i[2], 0.0, 0.0, 1.0, 0.0, 0.0, i[0], i[1], i[2], 0.0, 0.0, 0.0, 0.0, 1.0, i[0], i[1], i[2], 0.0, 1.0, 0.0, 0.0, 1.0, i[0], i[1], i[2], 1.0, 1.0, 0.0, 1.0, 1.0, i[0], i[1], i[2], 1.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2], 1.0, 1.0, 1.0, 1.0, 0.0, i[0], i[1], i[2], 0.0, 1.0, 1.0, 0.0, 0.0, i[0], i[1], i[2], 0.0, 1.0, 0.0, 0.0, 1.0, i[0], i[1], i[2], ]) print('Cube added!') def create_buffers(self): render_vbo, self.render_vao = glGenBuffers(1), glGenVertexArrays(1) glBindVertexArray(self.render_vao) glBindBuffer(GL_ARRAY_BUFFER, render_vbo) glBufferData(GL_ARRAY_BUFFER, np.array(self.render_list), GL_STATIC_DRAW) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(12)) glEnableVertexAttribArray(1) glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(20)) glEnableVertexAttribArray(2) def draw_buffer(self, program, texture): program.use() glBindTexture(GL_TEXTURE_2D, texture) glBindVertexArray(self.render_vao) glDrawArrays(GL_TRIANGLES, 0, int(len(self.render_list)/8))
初始化和渲染循环:
def main(): global delta_time, last_frame test_chunk = chunk.chunk((0,0,0)) #Creates a 16x16x16 cube of cubes test_chunk.fill_layers(0, 16, 1) #Works fine window = utilities.window() camera.setup_window(window) glEnable(GL_DEPTH_TEST) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) shader_program = utilities.shader(vertex_source_3d, fragment_source_3d, '330') shader_program.compile() #Check which cubes are exposed and should be rendered #Works fine exposed_list = [i for i, blocktype in np.ndenumerate(test_chunk.data) if test_chunk.return_if_exposed(i) == True and blocktype != 0] shader_program.use() shader_program.set_int('texture0', 0) camera_direction = glm.vec3() yaw = -90.0 second_counter = 0 frame_counter = 0 render = cube.render(exposed_list) render.create_buffers() while not window.check_if_closed(): current_frame = glfw.get_time() delta_time = current_frame - last_frame last_frame = current_frame second_counter += delta_time frame_counter += 1 window.refresh(0) camera.process_input(window, delta_time) camera.testing_commands(window) glActiveTexture(GL_TEXTURE0) shader_program.use() pos, looking, up = camera.return_vectors() view = glm.lookAt(pos, looking, up) projection = glm.perspective(glm.radians(45), window.size[0]/window.size[1], 0.1, 100) shader_program.set_mat4('view', glm.value_ptr(view)) shader_program.set_mat4('projection', glm.value_ptr(projection)) render.draw_buffer(shader_program, cobble_tex_ID) glBindVertexArray(0) if second_counter >= 1: print(frame_counter) second_counter, frame_counter = 0, 0 window.refresh(1) window.close() if __name__ == '__main__': main()
顶点着色器:
#version %s core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; layout (location = 2) in vec3 cube_coord; out vec2 TexCoord; uniform mat4 view; uniform mat4 projection; mat4 model = mat4(1.0); void main() { model[0].w = cube_coord.x; model[1].w = cube_coord.y; model[2].w = cube_coord.z; gl_Position = projection * view * model * vec4(aPos, 1.0); TexCoord = aTexCoord; }
片段着色器:
version %s core out vec4 FragColor; in vec2 TexCoord; uniform sampler2D texture0; void main() { FragColor = texture(texture0, TexCoord); }
将翻译分配给模型矩阵是错误的。 glsl 矩阵按列主要顺序存储。翻译是第 4 列。典型的模型矩阵如下所示:
mat4 m44 = mat4(
vec4( Xx, Xy, Xz, 0.0),
vec4( Yx, Xy, Yz, 0.0),
vec4( Zx Zy Zz, 0.0),
vec4( Tx, Ty, Tz, 1.0) );
您必须更改模型矩阵初始化:
mat4 model = mat4(1.0);
void main() {
model[3] = vec4(cube_coord.xyz, 1.0);
// [...]
}
此外,您必须为 numpy.array
(numpy.float32
) 指定数据类型:
glBufferData(GL_ARRAY_BUFFER, np.array(self.render_list), GL_STATIC_DRAW)
glBufferData(GL_ARRAY_BUFFER, np.array(self.render_list, np.float32), GL_STATIC_DRAW)
顶点数组是二维的,因此len(self.render_list)/8
不是顶点数:
glDrawArrays(GL_TRIANGLES, 0, int(len(self.render_list)/8))
no_of_verices = len(self.render_list) * 36
glDrawArrays(GL_TRIANGLES, 0, no_of_verices)
分别
no_of_verices = len(self.render_list) * len(self.render_list[0]) // 8
glDrawArrays(GL_TRIANGLES, 0, no_of_verices)