OpenGL 绘制数千个 2D 圆圈
在我的应用程序中,我在 3D 场景之上渲染数千个 (~10k) 2D 圆圈。我可以使用它,但是当有这么多圆圈时(圆圈很小,直径约为 16 像素),性能会非常慢。我用于绘制圆圈的代码如下所示:
for ( int i = 0; i < numCircles; i++) {
int attributeMask = GL.GL_DEPTH_BUFFER_BIT | GL.GL_TRANSFORM_BIT
| GL.GL_VIEWPORT_BIT | GL.GL_CURRENT_BIT
| GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT
| GL.GL_ENABLE_BIT | GL.GL_LIGHTING_BIT;
gl.glPushAttrib(attributeMask);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glDisable(GL.GL_LIGHTING);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glOrtho(0d, dc.getView().getViewport().width, 0d, dc.getView()
.getViewport().height, -1, 1);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glDisable(GL.GL_DEPTH_TEST);
Vec4 screenPt // this is calculated for each circle
double size = 16;
gl.glTranslated(screen.x, screen.y, 0d);
gl.glScaled(size, size, size);
gl.glCallList(fillListId);
gl.glCallList(outlineListId);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPopMatrix();
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glPopMatrix();
gl.glPopAttrib();
}
列表生成如下:
NUM_SEGMENTS = 18;
double[][] vertices = new double[2][NUM_SEGMENTS];
for (int i = 0; i < NUM_SEGMENTS; i++)
{
double rad = -2 * Math.PI * ((double) i) / ((double) NUM_SEGMENTS);
double x = Math.cos(rad);
double y = Math.sin(rad);
vertices[0][i] = x;
vertices[1][i] = y;
}
gl.glNewList(id, GL.GL_COMPILE);
gl.glBegin(GL.GL_LINE_LOOP); // 2 lists are actually created, the first time GL.GL_LINE_LOOP IS is used for the outline, and the second time GL.GL_POLYGON is used for the fill
for (int j = 0; j < vertices[0].length; j++)
{
gl.glVertex2d(vertices[0][j], vertices[1][j]);
}
gl.glEnd();
gl.glEndList();
我在这里做的事情是否明显错误以减慢渲染速度?我应该考虑在这里使用顶点缓冲区吗?或者还有其他技术可以加快速度吗?
谢谢, 杰夫
In my application, I am rendering thousands (~10k) 2D circles on top of a 3D scene. I have it working, but the performance is very slow when there are this many circles (the circles are small, ~16 pixels diameter). My code for drawing the circles looks like:
for ( int i = 0; i < numCircles; i++) {
int attributeMask = GL.GL_DEPTH_BUFFER_BIT | GL.GL_TRANSFORM_BIT
| GL.GL_VIEWPORT_BIT | GL.GL_CURRENT_BIT
| GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT
| GL.GL_ENABLE_BIT | GL.GL_LIGHTING_BIT;
gl.glPushAttrib(attributeMask);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glDisable(GL.GL_LIGHTING);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glOrtho(0d, dc.getView().getViewport().width, 0d, dc.getView()
.getViewport().height, -1, 1);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glDisable(GL.GL_DEPTH_TEST);
Vec4 screenPt // this is calculated for each circle
double size = 16;
gl.glTranslated(screen.x, screen.y, 0d);
gl.glScaled(size, size, size);
gl.glCallList(fillListId);
gl.glCallList(outlineListId);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPopMatrix();
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glPopMatrix();
gl.glPopAttrib();
}
The lists are generated as follows:
NUM_SEGMENTS = 18;
double[][] vertices = new double[2][NUM_SEGMENTS];
for (int i = 0; i < NUM_SEGMENTS; i++)
{
double rad = -2 * Math.PI * ((double) i) / ((double) NUM_SEGMENTS);
double x = Math.cos(rad);
double y = Math.sin(rad);
vertices[0][i] = x;
vertices[1][i] = y;
}
gl.glNewList(id, GL.GL_COMPILE);
gl.glBegin(GL.GL_LINE_LOOP); // 2 lists are actually created, the first time GL.GL_LINE_LOOP IS is used for the outline, and the second time GL.GL_POLYGON is used for the fill
for (int j = 0; j < vertices[0].length; j++)
{
gl.glVertex2d(vertices[0][j], vertices[1][j]);
}
gl.glEnd();
gl.glEndList();
Is there something I'm doing obviously wrong here to slow down the rendering? Should I consider using vertex buffers here? Or are there other techniques to speed this up?
Thanks,
Jeff
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以生成一个圆形,将其位块传输到纹理,然后仅创建使用该圆形进行纹理化的表面(两个三角形)。
You can generate a single circle, blit it to a texture, then just create surfaces (of two triangles) that are textured with that circle.
我认为所有这些代码
和所有这些代码都
可以在循环之外完成,并且只需完成一次。
您只需要推送和弹出对象平移/缩放的矩阵。
I would think all of this code
and all of this code
could be done outside of the loop, and just done once.
You would just need to push and pop a matrix for the object translate/scale.