C++ OpenGL渲染大量动态2D圆

C++ OpenGL渲染大量动态2D圆,c++,opengl,C++,Opengl,我看过一篇关于这个主题的类似帖子,但是,我的问题有点不同 我有一个二维图,它将由不同位置的圆圈组成,大小不一。目前,我的渲染方案使用一个显示列表来存储一个预绘制的圆,用户可以使用glScalef/GLTRANSTALEF主动调整和转换该圆的大小。但是,由于我正在渲染数千个圆,因此调整大小和绘制速度变得非常慢。每个圆可以有不同的半径和颜色,因此这些事情必须在循环中完成 当用户更改圆的大小时,我可以尝试哪些方法来提高圆的渲染速度?我已经像上面的链接所说的那样研究了VBO,但是对于我的对象大小不断变化

我看过一篇关于这个主题的类似帖子,但是,我的问题有点不同

我有一个二维图,它将由不同位置的圆圈组成,大小不一。目前,我的渲染方案使用一个显示列表来存储一个预绘制的圆,用户可以使用glScalef/GLTRANSTALEF主动调整和转换该圆的大小。但是,由于我正在渲染数千个圆,因此调整大小和绘制速度变得非常慢。每个圆可以有不同的半径和颜色,因此这些事情必须在循环中完成

当用户更改圆的大小时,我可以尝试哪些方法来提高圆的渲染速度?我已经像上面的链接所说的那样研究了VBO,但是对于我的对象大小不断变化的这种类型的应用程序,我将获得多少性能增益,这是不明确的。基于实例的可能是最干净的

您将有一个带有M个顶点的圆,您将绘制N次,将每个圆的x/y位置、半径和颜色存储为顶点属性,并适当地使用
glvertexattributedivisior()


如果需要半径自适应LOD,则会变得更加棘手。为此,您可能必须深入研究几何体着色器。

第二,使用带有GLDrawerElementsInstanced或GLDrawArrayInstanced的实例化数组作为干净的解决方案,可以很好地转移到其他类型的几何体

如果你想要/需要坚持OpenGL 2(eg必须运行在ITEN上),你只需要圆圈,也考虑点精灵。每个圆的原点是点的顶点值。将半径存储为纹理坐标的S值,曲面法线的X值,等等。启用混合、GL_程序_点_大小,可能是点平滑;编写一个顶点着色器,将gl_PointSize设置为所需的半径。即时循环

由于我正在渲染数千个圆,因此调整大小和绘制速度变得非常慢

仅使用顶点阵列,在具有10000个圆圈的Intel HD Graphics 3000上,每帧速度约为60毫秒:

// g++ -O3 circles.cpp -o circles -lglut -lGL
#include <GL/glut.h>
#include <vector>
#include <iostream>
#include <cmath>
using namespace std;

// returns a GL_TRIANGLE_FAN-able buffer containing a unit circle
vector< float > glCircle( unsigned int subdivs = 20 )
{
    vector< float > buf;

    buf.push_back( 0 );
    buf.push_back( 0 );
    for( unsigned int i = 0; i <= subdivs; ++i )
    {
        float angle = i * ((2.0f * 3.14159f) / subdivs);
        buf.push_back( cos(angle) );
        buf.push_back( sin(angle) );
    }

    return buf;
}

struct Circle
{
    Circle()
    {
        x = ( rand() % 200 ) - 100;
        y = ( rand() % 200 ) - 100;
        scale = ( rand() % 10 ) + 4;
        r = rand() % 255;
        g = rand() % 255;
        b = rand() % 255;
        a = 1;
    }

    float x, y;
    float scale;
    unsigned char r, g, b, a;
};

vector< Circle > circles;
vector< float > circleGeom;
void init()
{
    srand( 0 );
    for( size_t i = 0; i < 10000; ++i )
        circles.push_back( Circle() );
    circleGeom = glCircle( 100 );
}

void display()
{
    int beg = glutGet( GLUT_ELAPSED_TIME );

    glClear( GL_COLOR_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );
    double ar = w / h;
    glOrtho( -100 * ar, 100 * ar, -100, 100, -1, 1);

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glEnableClientState( GL_VERTEX_ARRAY );
    glVertexPointer( 2, GL_FLOAT, 0, &circleGeom[0] );

    for( size_t i = 0; i < circles.size(); ++i )
    {
        Circle& c = circles[i];
        c.scale = ( rand() % 10 ) + 4;

        glPushMatrix();
        glTranslatef( c.x, c.y, 0 );
        glScalef( c.scale, c.scale, 0 );
        glColor3ub( c.r, c.g, c.b );
        glDrawArrays( GL_TRIANGLE_FAN, 0, circleGeom.size() / 2 );
        glPopMatrix();
    }

    glDisableClientState( GL_VERTEX_ARRAY );

    glutSwapBuffers();

    int end = glutGet( GLUT_ELAPSED_TIME );
    double elapsed = (double)( end - beg );
    cout << elapsed << "ms" << endl;
}

void timer(int extra)
{
    glutPostRedisplay();
    glutTimerFunc(16, timer, 0);
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "Circles" );

    init();

    glutDisplayFunc( display );
    glutTimerFunc(0, timer, 0);
    glutMainLoop();
    return 0;
}
//g++-O3 circles.cpp-o circles-lglut-lGL
#包括
#包括
#包括
#包括
使用名称空间std;
//返回包含单位圆的GL\u三角形\u扇形缓冲区
向量glCircle(无符号整数细分向量=20)
{
向量buf;
buf.推回(0);
buf.推回(0);
对于(无符号整数i=0;i个圆;
向量循环;
void init()
{
srand(0);
对于(尺寸i=0;i<10000;++i)
圆圈。向后推(圆圈());
circleGeom=glCircle(100);
}
无效显示()
{
int beg=glutGet(GLUT_运行时间);
glClear(GLU颜色缓冲位);
glMatrixMode(GL_投影);
glLoadIdentity();
双w=glutGet(GLUT\U窗口\U宽度);
双h=glutGet(GLUT\U窗口\U高度);
双ar=w/h;
格洛托(-100*ar,100*ar,-100100,-1,1);
glMatrixMode(GLU模型视图);
glLoadIdentity();
glEnableClientState(GL_顶点_数组);
glVertexPointer(2,GL_FLOAT,0和circleGeom[0]);
对于(大小i=0;i难道你不应该研究现代OpenGL。
glScale
/
glTranslate
和家族在现代OpenGL中已经不复存在了。与你正在使用的旧版本相比,性能的提高是非常明显的。如果你能使用OpenGL 3.1或更高版本,那么就去吧。对于现代OpenGL的介绍。有多少个圆圈是“数千个圆圈”?10000?极慢有多慢?>每帧100毫秒?