万单位圈以上,如何画出高性能?

时间:2014-05-07 09:12:57

标签: c++ windows opengl

问题
在3D空间中,有很多要点。我需要在每个点的位置绘制一个单位圆。 并且所有圆圈的法线应始终垂直于设备的屏幕,而尺寸则不是 即使我旋转或放大/缩小视图,也会更改。 enter image description here

我的方法

首先,我有一个大数组来存储每个点的xyz坐标。

for each point in the array:
    apply a model view matrix  // to keep the normal perpendicular and the same size
    draw a unit circle with gl* functions

通过这种方法,当点数达到10000时,我得到一个非常糟糕的FPS。 这效率非常低。有没有更好的方法来解决这个问题?或者一些OpenGL 技术可以用吗?

3 个答案:

答案 0 :(得分:2)

您可以绘制instanced(自3.3或扩展ARB_instanced_arrays后可用)

为绘图准备一个单位圆(使用单独的属性作为您添加到顶点着色器中的点的位置)

每个点的位置放在一个单独的VBO中,并用

指定除数
void glVertexAttribDivisor​(GLuint index​, GLuint divisor​);

然后你使用

void glDrawArraysInstanced​( GLenum mode​, GLint first​, GLsizei count​, GLsizei instancecount​);

计算circleinstancecount点数的顶点数

答案 1 :(得分:1)

您的方法存在的问题是您需要的许多OpenGL调用。

首先,您应该将圈子建模为"粒子"。每个粒子都有一个位置,也许还有一个颜色。你甚至可以添加一个尺寸。

您可以通过两种方式渲染粒子:线圈(即圆圈)或带圆圈的Alpha混合粒子纹理。第一个使用更多顶点,并以某种方式限制它的外观。后者仅使用两个三角形,并且更加灵活,但填充率可能有点沉重。

对于这两种情况,您应首先创建渲染所需的所有基元(线条或四边形)。将顶点和索引存储在vertex buffer object中。然后你可以用一个绘制调用绘制。

使用现代OpenGL(3.2+),您可以使用geometry shaders在GPU上动态创建粒子网格。这可能更快。

详细过程并不复杂,但这里的答案范围不够。在互联网上搜索有关上述步骤的资源,并随时在此处提出更具体的问题。

答案 2 :(得分:0)

你有一个数组,每个点的XYZ位置。将所有数据复制到VBO中,您将用作顶点数据。

绘制代码只是glVertexAttribPointer(或带有VAO的glBindArray),然后是glDrawArrays,其中n ==数组中的点数。

通常这只会给你很多个点。

OpenGL具有点精灵,其中每个点都绘制为四边形,屏幕对齐,顶点着色器指定的像素大小。 (有一个实现限制,IIRC保证至少63像素,但这可能足以满足你的需要。)所以你需要启用GL_PROGRAM_POINT_SIZE并让你的顶点着色器为gl_PointSize赋值。 (如果你愿意的话,你可以根据透视距离来确定尺寸。)

最后一步是这些点精灵可以被纹理化。片段着色器为四元组内的每个像素获取0.0到1.0的纹理坐标作为内置gl_PointCoord。使用圆圈图像创建一个小纹理贴图,设置您不想透明的像素,并使用它来设置片段着色器中的颜色。

有关代码,请参阅第6版OpenGL SuperBible的第9章。希望这会有所帮助。