我正在关注pyOpenGL上相当陈旧的教程系列,而且我正在完成他的工作。然而,我遇到了滞后 - 我有AMD FX-6300与8GB RAM,GTX-1050ti和文件存储在闪存驱动器上。我看过一些使用glBegin
和glEnd
导致问题的地方?我应该使用什么,以及如何在此代码中执行此操作:
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import random
"""
- A Cube has 8 Nodes/Verticies
- 12 Lines/connections
- 6 Sides
"""
vertices = (
(1, -1, -1),
(1, 1, -1),
(-1, 1, -1),
(-1, -1, -1),
(1, -1, 1),
(1, 1, 1),
(-1, -1, 1),
(-1, 1, 1)
)
edges = ( #Contains vertexes/nodes
(0, 1),
(0, 3),
(0, 4),
(2, 1),
(2, 3),
(2, 7),
(6, 3),
(6, 4),
(6, 7),
(5, 1),
(5, 4),
(5, 7)
)
surfaces = (
(0,1,2,3),
(3,2,7,6),
(6,7,5,4),
(4,5,1,0),
(1,5,7,2),
(4,0,3,6),
)
colors = (
(1,0,0),
(0,1,0),
(0,0,1),
(0,0,0,),
(1,1,1),
(0,1,1),
(1,0,0),
(0,1,0),
(0,0,1),
(0,0,0,),
(1,1,1),
(0,1,1),
)
def set_vertices(max_distance):
#Create change between each cube
x_value_change = random.randrange(-10, 10)
y_value_change = random.randrange(-10, 10)
z_value_change = random.randrange(-1 * max_distance, -20)
new_vertices = []
for vert in vertices:
new_vert = []
new_x = vert[0] + x_value_change
new_y = vert[1] + y_value_change
new_z = vert[2] + z_value_change
new_vert.append(new_x)
new_vert.append(new_y)
new_vert.append(new_z)
new_vertices.append(new_vert) #Appends (1, 1, 1)
return new_vertices
def Cube(veritces):
glBegin(GL_QUADS)
for surface in surfaces:
x = 0
for vertex in surface:
x += 1
glColor3fv((colors[x]))
glVertex3fv(vertices[vertex])
glEnd()
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(vertices[vertex]) #Draws vertex's in position given according to vertices array
glEnd()
def main():
pygame.init()
display = (1000, 800)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0) #FOV, aspect ratio. clipping plane min, max
glTranslatef(random.randrange(-5, 5), random.randrange(-5, 5), -40) #X,Y,Z -5 to zoom out on z axis
#glRotatef(25, 1, 20, 0) #Degrees, x,y,z
object_passed = False
max_distance = 300
cube_dict = {}
for x in range(75): #Draws 75 cubes
cube_dict[x] = set_vertices(max_distance) #Returns a new cube set of vertices
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_move = 0.3
if event.key == pygame.K_RIGHT:
x_move = -0.3
if event.key == pygame.K_UP:
y_move = -0.3
if event.key == pygame.K_DOWN:
y_move = 0.3
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_move = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_move = 0
"""
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 4:
glTranslatef(0, 0, 1)
if event.button == 5:
glTranslatef(0, 0, -1)
"""
#glRotatef(1, 1, 1, 1)
x = glGetDoublev(GL_MODELVIEW_MATRIX)
camera_x = x[3][0] #Access camera cordinates
camera_y = x[3][1]
camera_z = x[3][2]
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) #Clears the screen
glTranslatef(x_move, y_move, 0.5)
for each_cube in cube_dict:
Cube(cube_dict[each_cube])
pygame.display.flip() #Cant use update
pygame.time.wait(10)
main()
pygame.quit()
quit()
教程为here
谢谢!
答案 0 :(得分:2)
我看过一些使用
glBegin
和glEnd
导致问题的地方?我该怎么用......
现代OpenGL中不推荐使用glBegin
和glEnd
绘图
(见Fixed Function Pipeline和
Legacy OpenGL)。
在现代OpenGL Vertices are Specified中
Vertex Buffer Objects和
Vertex Array Object
并且使用Shader program绘制evrything。
作为朝这个方向迈出的第一步,我建议使用Vertex Buffer Objects和客户端功能
命令
void VertexPointer( int size, enum type, sizei stride, const void *pointer ); void NormalPointer( enum type, sizei stride, const void *pointer ); void ColorPointer( int size, enum type, sizei stride, const void *pointer ); void SecondaryColorPointer( int size, enum type, sizei stride, const void *pointer ); void IndexPointer( enum type, sizei stride, const void *pointer ); void EdgeFlagPointer( sizei stride, const void *pointer ); void FogCoordPointer( enum type, sizei stride, const void *pointer ); void TexCoordPointer( int size, enum type, sizei stride, const void *pointer );
指定数组的位置和组织,以存储顶点坐标,法线,颜色,二次颜色,颜色索引,边缘标志,雾坐标。
...
通过调用
之一启用或禁用单个阵列void EnableClientState( enum array ); void DisableClientState( enum array );
将数组设置为
VERTEX_ARRAY
,NORMAL_ARRAY
,COLOR_ARRAY
,SECONDARY_COLOR_ARRAY
,INDEX_ARRAY
,EDGE_FLAG_ARRAY
,FOG_COORD_ARRAY
或TEXTURE_COORD_ARRAY
,分别用于顶点,法线,颜色,辅助颜色,颜色索引,边缘标志,雾坐标或纹理坐标数组。
为此,您必须做好准备,并且必须包含NumPy:
import numpy
为顶点缓冲区对象创建全局变量
global face_vbos, edge_vbo
为面创建属性集(颜色和顶点坐标对),并为面创建顶点缓冲区对象(顶点坐标和颜色)。 最后为边的顶点坐标创建顶点缓冲区对象:
def main():
global face_vbos, edge_vbo
.....
# define the vertex buffers vor the faces
vertex_array = []
color_array = []
for face in range(len(surfaces)):
for vertex in surfaces[face]:
vertex_array .append( vertices[vertex] )
color_array.append( colors[face] )
face_vbos = glGenBuffers(2)
glBindBuffer(GL_ARRAY_BUFFER, face_vbos[0])
glBufferData( GL_ARRAY_BUFFER, numpy.array( vertex_array, dtype=numpy.float32 ), GL_STATIC_DRAW )
glBindBuffer(GL_ARRAY_BUFFER, face_vbos[1])
glBufferData( GL_ARRAY_BUFFER, numpy.array( color_array, dtype=numpy.float32 ), GL_STATIC_DRAW )
glBindBuffer(GL_ARRAY_BUFFER, 0)
# define the vertex buffer for the edges
edge_vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, edge_vbo)
glBufferData( GL_ARRAY_BUFFER, numpy.array( vertices, dtype=numpy.float32 ), GL_STATIC_DRAW )
glBindBuffer(GL_ARRAY_BUFFER, 0)
while True:
.....
当你绘制面和边时,你已经定义了一个顶点数据数组(glVertexPointer
)
并定义颜色数组(glColorPointer
)
启用客户端功能(glEnableClientState
)
面部可以由glDrawArrays
绘制,因为所有坐标都存储了颜色
一个连续的数组(vertex_array
和color_array
- > face_vbos
)
边缘必须由glDrawElements
绘制,使用索引edges
,
因为必须将顶点(vertices
- > edge_vbo
)编入索引以形成线:
def Cube(veritces):
global face_vbos, edge_vbo
# draw faces
glBindBuffer(GL_ARRAY_BUFFER, face_vbos[0])
glVertexPointer( 3, GL_FLOAT, 0, None )
glEnableClientState( GL_VERTEX_ARRAY )
glBindBuffer(GL_ARRAY_BUFFER, face_vbos[1])
glColorPointer( 3, GL_FLOAT, 0, None )
glEnableClientState( GL_COLOR_ARRAY )
glBindBuffer(GL_ARRAY_BUFFER, 0)
glDrawArrays(GL_QUADS, 0, 6*4)
glDisableClientState( GL_VERTEX_ARRAY )
glDisableClientState( GL_COLOR_ARRAY )
#draw edges
glBindBuffer(GL_ARRAY_BUFFER, edge_vbo)
glVertexPointer( 3, GL_FLOAT, 0, None )
glEnableClientState( GL_VERTEX_ARRAY )
glBindBuffer(GL_ARRAY_BUFFER, 0)
glColor3f( 1, 1, 0 )
glDrawElements(GL_LINES, 2*12, GL_UNSIGNED_INT, numpy.array( edges, dtype=numpy.uint32 ))
glDisableClientState( GL_VERTEX_ARRAY )
使用Vertex Array Objects可以进一步改善这一点 边缘为Index buffer:
global face_vao, edge_vao
def main():
global face_vao, edge_vao
.....
# define the vertex buffers vor the faces
attribute_array = []
for face in range(len(surfaces)):
for vertex in surfaces[face ]:
attribute_array.append( vertices[vertex] )
attribute_array.append( colors[face] )
face_vbos = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, face_vbos)
glBufferData( GL_ARRAY_BUFFER, numpy.array( attribute_array, dtype=numpy.float32 ), GL_STATIC_DRAW )
glBindBuffer(GL_ARRAY_BUFFER, 0)
# define the vertex array object for the faces
face_vao = glGenVertexArrays( 1 )
glBindVertexArray( face_vao )
glBindBuffer(GL_ARRAY_BUFFER, face_vbos)
glVertexPointer( 3, GL_FLOAT, 6*4, None )
glEnableClientState( GL_VERTEX_ARRAY )
glColorPointer( 3, GL_FLOAT, 6*4, ctypes.cast(3*4, ctypes.c_void_p) )
glEnableClientState( GL_COLOR_ARRAY )
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray( 0 )
# define the vertex buffer for the edges
edge_vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, edge_vbo)
glBufferData( GL_ARRAY_BUFFER, numpy.array( vertices, dtype=numpy.float32 ), GL_STATIC_DRAW )
glBindBuffer(GL_ARRAY_BUFFER, 0)
# define the vertex array object for the edges
edge_vao = glGenVertexArrays( 1 )
glBindVertexArray( edge_vao )
glBindBuffer(GL_ARRAY_BUFFER, edge_vbo)
glVertexPointer( 3, GL_FLOAT, 0, None )
glEnableClientState( GL_VERTEX_ARRAY )
glBindBuffer(GL_ARRAY_BUFFER, 0)
edge_ibo = glGenBuffers(1)
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, edge_ibo )
glBufferData( GL_ELEMENT_ARRAY_BUFFER, numpy.array( edges, dtype=numpy.uint32 ), GL_STATIC_DRAW )
glBindVertexArray( 0 )
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 )
while True:
.....
def Cube(veritces):
global face_vao, edge_vao
# draw faces
glBindVertexArray( face_vao )
glDrawArrays( GL_QUADS, 0, 6*4 )
glBindVertexArray( 0 )
#draw edges
glColor3f( 1, 1, 0 )
glBindVertexArray( edge_vao )
glDrawElements( GL_LINES, 2*12, GL_UNSIGNED_INT, None )
glBindVertexArray( 0 )
Face Culling可以获得进一步的性能提升 和Depth Test。 深度测试应该更少或者是eauel,这样边缘不会被面覆盖:
# enable depth test (less or equal)
glEnable( GL_DEPTH_TEST )
glDepthFunc( GL_LEQUAL )
# enable back face culling (front faces are drawn clockwise)
glEnable( GL_CULL_FACE )
glCullFace( GL_BACK )
glFrontFace( GL_CW )
注意,在"现代"中绘制几何图形的最后一步在OpenGL中的方式是使用Shader program和
分别按glEnableClientState
和glEnableVertexAttribArray
glVertexPointer
替换glColorPointer
glVertexAttribPointer
(当然通过使用适当的参数)。