问题:
在3D空间中,有很多要点。我需要在每个点的位置绘制一个单位圆。
并且所有圆圈的法线应始终垂直于设备的屏幕,而尺寸则不是
即使我旋转或放大/缩小视图,也会更改。
我的方法:
首先,我有一个大数组来存储每个点的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 技术可以用吗?
答案 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);
计算circle
和instancecount
点数的顶点数
答案 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章。希望这会有所帮助。