Pygame OpenGL 3D多维数据集滞后 [英] Pygame OpenGL 3D Cube Lag

查看:67
本文介绍了Pygame OpenGL 3D多维数据集滞后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注pyOpenGL上的一个相当老的教程系列,我的工作完全和他一样.但是我遇到了滞后-我的AMD FX-6300带有8GB内存,GTX-1050ti,文件存储在闪存驱动器上.我已经阅读了一些使用 glBegin glEnd 引起问题的地方?我应该改用什么,以及如何在此代码中完成该操作:

I am following a tutorial series that is rather old on pyOpenGL and I am doing exactly as he does. However I am experiencing lag - I have AMD FX-6300 with 8gb ram, GTX-1050ti and files are stored on a flashdrive. I have read some places that using glBegin and glEnd cause issues? What should I use instead and how would I do it in this code:

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()

该教程是此处

谢谢!

推荐答案

我已经阅读了一些使用 glBegin glEnd 引起问题的地方?我应该改用什么...

I have read some places that using glBegin and glEnd cause issues? What should I use instead ...

在现代OpenGL中不建议使用 glBegin glEnd 进行绘制(请参见固定功能管道旧版OpenGL ).在现代OpenGL中,指定了顶点顶点缓冲区对象顶点数组对象然后使用 Shader程序绘制每个图像.

Drawing by glBegin and glEnd is deprecated in modern OpenGL (see Fixed Function Pipeline and Legacy OpenGL). In modern OpenGL Vertices are Specified by Vertex Buffer Objects and Vertex Array Object and evrything is drawn using a Shader program.

作为朝这个方向迈出的第一步,我建议使用顶点缓冲区对象和客户端-辅助功能

As a first step to this direction I recommend to use Vertex Buffer Objects and client-side capability

请参见 OpenGL 4.6 API兼容性配置文件规范;10.3.3为固定功能属性指定数组;第402页

命令

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 );

指定数组的位置和组织,以存储顶点坐标,法线,颜色,辅助颜色,颜色索引,边缘标志,雾坐标.

specify the location and organization of arrays to store vertex coordinates, normals, colors, secondary colors, color indices, edge flags, fog coordinates.

[...]

通过调用以下其中一个来启用或禁用单个数组

An individual array is enabled or disabled by calling one of

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 ,用于顶点,法线,颜色,辅助颜色,颜色索引,边缘标志,雾坐标,或纹理坐标数组.

with array set to VERTEX_ARRAY, NORMAL_ARRAY, COLOR_ARRAY, SECONDARY_COLOR_ARRAY, INDEX_ARRAY, EDGE_FLAG_ARRAY, FOG_COORD_ARRAY, or TEXTURE_COORD_ARRAY, for the vertex, normal, color, secondary color, color index, edge flag, fog coordinate, or texture coordinate array, respectively.

为此,您必须准备并且必须包含 NumPy :

To do so you have to prepare and you have to include NumPy:

import numpy

为顶点缓冲区对象创建全局变量,为面创建属性集(颜色和顶点坐标对),为面创建顶点缓冲区对象(顶点坐标和颜色).最后,为边缘的顶点坐标创建顶点缓冲区对象:

Create global variables for the vertex buffer objects and create attribute sets (pairs of color and vertex coordinate) for the faces and create the vertex buffer objects for the faces (vertex coordinate and color). Finally create the vertex buffer object for the vertices coordinates of the edges:

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:

        # [...]

在绘制面和边时,您已经定义了一组顶点数据( glColorPointer )启用客户端功能( glEnableClientState ).
可以通过 glDrawArrays 来绘制面孔,因为所有坐标的颜色都存储在其中连续数组( vertex_array color_array -> face_vbos ).
边缘必须通过 glDrawElements ,使用索引 edges ,因为必须将顶点(顶点-> edge_vbo )编入索引以形成线:

When you draw the faces and edges the you have define an array of vertex data (glVertexPointer ) and to define an array of colors (glColorPointer) to enable the client-side capability (glEnableClientState).
The faces can be drawn by glDrawArrays, since all the coordinates a colors are stored in an consecutive array (vertex_array and color_array -> face_vbos ).
The edges have to be drawn by glDrawElements, using the indices edges, since the vertices (vertices -> edge_vbo) have to be indexed to form lines:

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 )  


这可以通过使用顶点数组对象进一步加以改进边缘的索引缓冲区:


This can be further improved by using Vertex Array Objects and an Index buffer for the edges:

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 )


通过面部剔除,您可以进一步提高性能并加入深度测试.深度测试应小于或等于eauel,以使边缘不会被面孔覆盖:


An further performance imporvement you can gain by Face Culling and enbaling the Depth Test. The depth test should be less or eauel, so that the edges are not covered by the faces:

# 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程序并将 glEnableClientState 分别替换为 glEnableVertexAttribArray glVertexPointer 并将 glColorPointer 替换为 glVertexAttribPointer (当然使用适当的参数).


Note, the last step to draw geometry in a "modern" way in OpenGL would be to use a Shader program and to replace glEnableClientState by glEnableVertexAttribArray and glVertexPointer respectively glColorPointer by glVertexAttribPointer (of course by using the proper parameters).

另请参见 PyGame和OpenGL 4 .

这篇关于Pygame OpenGL 3D多维数据集滞后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆