有没有一种方法可以更快地渲染点 OpenGL
is there a way to render points faster OpenGL
我需要在 openGL 中可视化大约 50k-60k 点我设法将它们全部打印出来,但是当我使用旋转时,每次旋转之间需要很长时间,因为它只是在每一帧打印所有数据。
有没有办法一次打印所有数据并冻结数据的导入,这样它会保留图像但停止处理?
def PointClouds(pcd_files): #pcd_file
glBegin(GL_POINTS)
for i in pcd_files:
pc = pypcd.PointCloud.from_path(i)
number_of_points = pc.get_metadata().get('points')
z = pc.pc_data['z']
x = pc.pc_data['x']
y = pc.pc_data['y']
for j in range(number_of_points):
glVertex3f(x[j], y[j], z[j])
glEnd()
主要是:
files = glob.glob(os.getcwd() + "\" + PCD_OutPutDirectory + "\*.pcd")
pygame.init()
display = (1700, 1000)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
gluPerspective(50, (display[0] / display[1]), 0.1, 5000)
glTranslatef(0, 0, -1000)
Clock = pygame.time.Clock()
while True:
Clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef(2, 1, 1, 3)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
PointClouds(files)
pygame.display.flip()
打印所有点,但在每次旋转之间遍历所有点并再次打印它们,因为有 60k+ 点,每次旋转之间花费太多时间。我需要它只读取一次点并冻结图像而不是旋转。
感谢帮助
瓶颈是for循环和glBegin
/glEnd
序列。从每一帧的文件中读取数据。
请注意,几十年来不推荐使用 glBegin
/glEnd
序列和固定函数矩阵堆栈进行绘制。
在启动时读取文件一次并创建一个 Vertex Buffer Object。
(阅读更多关于 Vertex Specification and Shader 的 state-of-the-art 渲染方式。)
最接近现有代码的解决方案是使用客户端功能 glEnableClientState
and fixed function attributes glVertexPointer
。使用此解决方案,您不需要任何着色器程序。
在下文中,我假设您使用 PyOpenGL.
将顶点坐标加载到数组
def LoadVertices(pcd_files):
vertices = []
for i in pcd_files:
pc = pypcd.PointCloud.from_path(i)
number_of_points = pc.get_metadata().get('points')
z = pc.pc_data['z']
x = pc.pc_data['x']
y = pc.pc_data['y']
for j in range(number_of_points):
vertices += [x[j], y[j], z[j]]
return vertices
创建 Vertex Buffer Object 并创建和初始化缓冲区对象的数据存储:
import ctypes
def CreateBuffer(vertices):
bufferdata = (ctypes.c_float*len(vertices))(*vertices) # float buffer
buffersize = len(vertices)*4 # buffer size in bytes
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, buffersize, bufferdata, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0)
return vbo
创建一个可以从缓冲区中提取 Point primitives 的函数:
def DrawBuffer(vbo, noOfVertices):
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, 0, None)
glDrawArrays(GL_POINTS, 0, noOfVertices)
glDisableClientState(GL_VERTEX_ARRAY)
glBindBuffer(GL_ARRAY_BUFFER, 0)
在你的程序中使用这个函数:
files = glob.glob(os.getcwd() + "\" + PCD_OutPutDirectory + "\*.pcd")
pygame.init()
display = (1700, 1000)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
vArray = LoadVertices(files)
noPoints = len(vArray) // 3
bufferObj = CreateBuffer(vArray)
gluPerspective(50, (display[0] / display[1]), 0.1, 5000)
glTranslatef(0, 0, -1000)
Clock = pygame.time.Clock()
while True:
Clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef(2, 1, 1, 3)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
DrawBuffer(bufferObj, noPoints)
pygame.display.flip()
如果你想为每个点添加单独的颜色,那么顶点及其属性不仅由坐标(x, y, z)
组成,还必须RGB color(x, y, z, r, g, b)
, 因此每个属性元组由 6 个组件而不是 3 个组成。
固定功能颜色属性必须由客户端状态启用 GL_COLOR_ARRAY
。添加属性指定为glColorPointer
.
每个属性元组的大小为 24 字节,因为一个元组由 6 个组件 (x, y, z, r, g, b)
组成,每个组件的大小为 4 字节(这是 float
的大小)。
此大小必须分别传递给 glVertexPointer
的第三个参数 (sride
) glColorPointer
.
如果绑定了命名缓冲区对象,则 glVertexPointer
和 glColorPointer
的最后一个参数将被视为缓冲区对象缓冲区存储中的字节偏移量。偏移量是到属性第一个组件的字节数。
在 glVertexPointer
的情况下,偏移量为 0,因为 (x, y, z)
是属性元组中的第一个组件。
在 glColorPointer
的情况下,偏移量为 3*4=12 个字节,因为 (r, g, b)
在 3 个坐标 (x, y, z)
之后,每个组件的大小为 4。
由于最后一个参数的类型是指针,偏移量必须转换为 ctypes.c_void_p
(例如 ctypes.c_void_p(3*4)
)。为此 python built-in 必须导入库 。如果偏移量为0,可以用None
代替ctypes.c_void_p(0)
.
顶点属性的规范可能如下所示:
glBindBuffer(GL_ARRAY_BUFFER, vbo)
stride = 6*4 # (24 bates) : [x, y, z, r, g, b] * sizeof(float)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, stride, None)
glEnableClientState(GL_COLOR_ARRAY)
offset = 3*4 # (12 bytes) : the rgb color starts after the 3 coordinates x, y, z
glColorPointer(3, GL_FLOAT, stride, ctypes.c_void_p(offset))
总计:
import ctypes
def LoadVertices(pcd_files):
attributes = []
for i in pcd_files:
pc = pypcd.PointCloud.from_path(i)
number_of_points = pc.get_metadata().get('points')
z = pc.pc_data['z']
x = pc.pc_data['x']
y = pc.pc_data['y']
r = # set the RGB color data here
g =
b =
for j in range(number_of_points):
attributes += [x[j], y[j], z[j], r[j], g[j], b[j]]
return attributes
def CreateBuffer(attributes):
bufferdata = (ctypes.c_float*len(attributes))(*attributes) # float buffer
buffersize = len(attributes)*4 # buffer size in bytes
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, buffersize, bufferdata, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0)
return vbo
def DrawBuffer(vbo, noOfVertices):
glBindBuffer(GL_ARRAY_BUFFER, vbo)
stride = 6*4 # (24 bates) : [x, y, z, r, g, b] * sizeof(float)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, stride, None)
glEnableClientState(GL_COLOR_ARRAY)
offset = 3*4 # (12 bytes) : the rgb color starts after the 3 coordinates x, y, z
glColorPointer(3, GL_FLOAT, stride, ctypes.c_void_p(offset))
glDrawArrays(GL_POINTS, 0, noOfVertices)
glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_COLOR_ARRAY)
glBindBuffer(GL_ARRAY_BUFFER, 0)
files = glob.glob(os.getcwd() + "\" + PCD_OutPutDirectory + "\*.pcd")
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
vArray = LoadVertices(files)
noPoints = len(vArray) // 6 # 6 components per attribute tuple
bufferObj = CreateBuffer(vArray)
gluPerspective(50, (display[0] / display[1]), 0.1, 5000)
glTranslatef(0, 0, -1000)
Clock = pygame.time.Clock()
while True:
Clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef(2, 1, 1, 3)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
DrawBuffer(bufferObj, noPoints)
pygame.display.flip()
我需要在 openGL 中可视化大约 50k-60k 点我设法将它们全部打印出来,但是当我使用旋转时,每次旋转之间需要很长时间,因为它只是在每一帧打印所有数据。 有没有办法一次打印所有数据并冻结数据的导入,这样它会保留图像但停止处理?
def PointClouds(pcd_files): #pcd_file
glBegin(GL_POINTS)
for i in pcd_files:
pc = pypcd.PointCloud.from_path(i)
number_of_points = pc.get_metadata().get('points')
z = pc.pc_data['z']
x = pc.pc_data['x']
y = pc.pc_data['y']
for j in range(number_of_points):
glVertex3f(x[j], y[j], z[j])
glEnd()
主要是:
files = glob.glob(os.getcwd() + "\" + PCD_OutPutDirectory + "\*.pcd")
pygame.init()
display = (1700, 1000)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
gluPerspective(50, (display[0] / display[1]), 0.1, 5000)
glTranslatef(0, 0, -1000)
Clock = pygame.time.Clock()
while True:
Clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef(2, 1, 1, 3)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
PointClouds(files)
pygame.display.flip()
打印所有点,但在每次旋转之间遍历所有点并再次打印它们,因为有 60k+ 点,每次旋转之间花费太多时间。我需要它只读取一次点并冻结图像而不是旋转。 感谢帮助
瓶颈是for循环和glBegin
/glEnd
序列。从每一帧的文件中读取数据。
请注意,几十年来不推荐使用 glBegin
/glEnd
序列和固定函数矩阵堆栈进行绘制。
在启动时读取文件一次并创建一个 Vertex Buffer Object。
(阅读更多关于 Vertex Specification and Shader 的 state-of-the-art 渲染方式。)
最接近现有代码的解决方案是使用客户端功能 glEnableClientState
and fixed function attributes glVertexPointer
。使用此解决方案,您不需要任何着色器程序。
在下文中,我假设您使用 PyOpenGL.
将顶点坐标加载到数组
def LoadVertices(pcd_files):
vertices = []
for i in pcd_files:
pc = pypcd.PointCloud.from_path(i)
number_of_points = pc.get_metadata().get('points')
z = pc.pc_data['z']
x = pc.pc_data['x']
y = pc.pc_data['y']
for j in range(number_of_points):
vertices += [x[j], y[j], z[j]]
return vertices
创建 Vertex Buffer Object 并创建和初始化缓冲区对象的数据存储:
import ctypes
def CreateBuffer(vertices):
bufferdata = (ctypes.c_float*len(vertices))(*vertices) # float buffer
buffersize = len(vertices)*4 # buffer size in bytes
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, buffersize, bufferdata, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0)
return vbo
创建一个可以从缓冲区中提取 Point primitives 的函数:
def DrawBuffer(vbo, noOfVertices):
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, 0, None)
glDrawArrays(GL_POINTS, 0, noOfVertices)
glDisableClientState(GL_VERTEX_ARRAY)
glBindBuffer(GL_ARRAY_BUFFER, 0)
在你的程序中使用这个函数:
files = glob.glob(os.getcwd() + "\" + PCD_OutPutDirectory + "\*.pcd")
pygame.init()
display = (1700, 1000)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
vArray = LoadVertices(files)
noPoints = len(vArray) // 3
bufferObj = CreateBuffer(vArray)
gluPerspective(50, (display[0] / display[1]), 0.1, 5000)
glTranslatef(0, 0, -1000)
Clock = pygame.time.Clock()
while True:
Clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef(2, 1, 1, 3)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
DrawBuffer(bufferObj, noPoints)
pygame.display.flip()
如果你想为每个点添加单独的颜色,那么顶点及其属性不仅由坐标(x, y, z)
组成,还必须RGB color(x, y, z, r, g, b)
, 因此每个属性元组由 6 个组件而不是 3 个组成。
固定功能颜色属性必须由客户端状态启用 GL_COLOR_ARRAY
。添加属性指定为glColorPointer
.
每个属性元组的大小为 24 字节,因为一个元组由 6 个组件 (x, y, z, r, g, b)
组成,每个组件的大小为 4 字节(这是 float
的大小)。
此大小必须分别传递给 glVertexPointer
的第三个参数 (sride
) glColorPointer
.
如果绑定了命名缓冲区对象,则 glVertexPointer
和 glColorPointer
的最后一个参数将被视为缓冲区对象缓冲区存储中的字节偏移量。偏移量是到属性第一个组件的字节数。
在 glVertexPointer
的情况下,偏移量为 0,因为 (x, y, z)
是属性元组中的第一个组件。
在 glColorPointer
的情况下,偏移量为 3*4=12 个字节,因为 (r, g, b)
在 3 个坐标 (x, y, z)
之后,每个组件的大小为 4。
由于最后一个参数的类型是指针,偏移量必须转换为 ctypes.c_void_p
(例如 ctypes.c_void_p(3*4)
)。为此 python built-in 必须导入库 None
代替ctypes.c_void_p(0)
.
顶点属性的规范可能如下所示:
glBindBuffer(GL_ARRAY_BUFFER, vbo)
stride = 6*4 # (24 bates) : [x, y, z, r, g, b] * sizeof(float)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, stride, None)
glEnableClientState(GL_COLOR_ARRAY)
offset = 3*4 # (12 bytes) : the rgb color starts after the 3 coordinates x, y, z
glColorPointer(3, GL_FLOAT, stride, ctypes.c_void_p(offset))
总计:
import ctypes
def LoadVertices(pcd_files):
attributes = []
for i in pcd_files:
pc = pypcd.PointCloud.from_path(i)
number_of_points = pc.get_metadata().get('points')
z = pc.pc_data['z']
x = pc.pc_data['x']
y = pc.pc_data['y']
r = # set the RGB color data here
g =
b =
for j in range(number_of_points):
attributes += [x[j], y[j], z[j], r[j], g[j], b[j]]
return attributes
def CreateBuffer(attributes):
bufferdata = (ctypes.c_float*len(attributes))(*attributes) # float buffer
buffersize = len(attributes)*4 # buffer size in bytes
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, buffersize, bufferdata, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0)
return vbo
def DrawBuffer(vbo, noOfVertices):
glBindBuffer(GL_ARRAY_BUFFER, vbo)
stride = 6*4 # (24 bates) : [x, y, z, r, g, b] * sizeof(float)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, stride, None)
glEnableClientState(GL_COLOR_ARRAY)
offset = 3*4 # (12 bytes) : the rgb color starts after the 3 coordinates x, y, z
glColorPointer(3, GL_FLOAT, stride, ctypes.c_void_p(offset))
glDrawArrays(GL_POINTS, 0, noOfVertices)
glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_COLOR_ARRAY)
glBindBuffer(GL_ARRAY_BUFFER, 0)
files = glob.glob(os.getcwd() + "\" + PCD_OutPutDirectory + "\*.pcd")
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
vArray = LoadVertices(files)
noPoints = len(vArray) // 6 # 6 components per attribute tuple
bufferObj = CreateBuffer(vArray)
gluPerspective(50, (display[0] / display[1]), 0.1, 5000)
glTranslatef(0, 0, -1000)
Clock = pygame.time.Clock()
while True:
Clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef(2, 1, 1, 3)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
DrawBuffer(bufferObj, noPoints)
pygame.display.flip()