问题 :
在3D空间中,有许多要点。 我需要在每个点的位置绘制一个单位圆。 即使我旋转或放大/缩小视图,所有界面的正常情况都应该始终垂直于设备的屏幕,并且尺寸不会改变。
我的方法 :
起初我有一个大arrays来存储每个点的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技术?
你可以绘制他们instanced (自3.3或扩展ARB_instanced_arrays
)
您准备绘制一个单位圆(使用单独的属性为您添加到顶点着色器中的点的位置)
每个点的位置都放在一个单独的VBO中,并用指定的除数
void glVertexAttribDivisor(GLuint index, GLuint divisor);
然后你使用
void glDrawArraysInstanced( GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
用你的circle
数顶点数和instancecount
点数
你的方法的问题是许多你需要的OpenGL调用。
首先你应该把你的圈子塑造成“粒子”。 每个粒子都有一个位置,也许还有一个颜色。 你甚至可以添加一个尺寸。
您可以通过两种方式渲染粒子:线条循环(即圆形)或具有圆形的alpha混合粒子纹理。 第一个使用更多的顶点,不知何故局限于它的外观。 后者只使用两个三角形,并且更加灵活,但是填充率可能有点大。
对于这两种情况,您应该首先创建呈现所需的所有图元(线或四边形)。 将顶点和索引存储在顶点缓冲区对象中 。 然后你可以画一个平局。
使用现代OpenGL(3.2+),您可以使用几何着色器在GPU上实时创建粒子网格。 这可能更快。
详细的过程不是很复杂,但在这里没有答案的范围。 在互联网上搜索上述步骤的资源,并随时提出更具体的问题。
你有一个数组,每个点的XYZ位置。 将所有的数据复制到一个VBO中,你将用它作为顶点数据。
绘制代码将只是glVertexAttribPointer(或带有VAO的glBindArray),然后glDrawArrays与n ==数组中的点数。
通常这会给你很多个人点。
OpenGL有点精灵,每个点绘制为一个四边形,屏幕对齐,顶点着色器指定的像素大小。 (有一个实现的限制,IIRC保证至少63像素,但这可能足够大的情况下)。所以你需要启用GL_PROGRAM_POINT_SIZE,并让你的顶点着色器分配一些gl_PointSize。 (如果你喜欢的话,你可以根据视角的距离做出尺寸。)
最后一步是这些点精灵可以被纹理化。 片段着色器为内建gl_PointCoord的四边形内的每个像素获取0.0到1.0的纹理坐标。 用你的圆圈的图像创建一个小的纹理贴图,设置你不想透明的像素,并使用它来设置你的片段着色器的颜色。
代码请参阅第6版OpenGL SuperBible的第9章。 希望这可以帮助。