2012-11-21 4 views
3

이 주제에 관한 비슷한 게시물을 보았습니다. here 그러나 내 질문은 약간 다릅니다.많은 양의 동적 2D 원을 렌더링하는 OpenGL

다양한 크기의 다양한 위치에서 원으로 구성되는 2D 플롯이 있습니다. 현재 렌더링 스키마는 표시 목록을 사용하여 glScalef/glTranslatef를 사용하여 사용자가 활발히 크기를 조정하고 번역 할 수있는 미리 그려진 원을 저장합니다. 그러나 수천 개의 서클을 렌더링하기 때문에 크기 조정과 드로잉이 매우 느려집니다. 각 원은 서로 다른 반지름과 색상을 가질 수 있으므로 이러한 것들은 루프 내에서 이루어져야합니다.

사용자가 서클 크기를 변경했을 때 서클 렌더링 속도를 향상시킬 수있는 방법은 무엇입니까? 위의 링크처럼 VBO를 살펴 봤지만 내 객체의 크기가 계속 변하는이 유형의 응용 프로그램에서 성능 향상이 얼마나 많이 발생하는지 모호했습니다.

+2

최신 OpenGL을 살펴보아야합니다. 'glScale' /'glTranslate'와 패밀리는 현대 OpenGL에서 더 이상 존재하지 않습니다. 성능 향상은 사용중인 레거시 버전과 비교할 때 상당히 두드러 질 수 있습니다. OpenGL 3.1 이상을 사용할 수 있으면 수행하십시오. [이 페이지를 확인하십시오] (http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-1:The-Graphics-Pipeline.html) 최신 OpenGL 소개. – Cornstalks

+0

"서클 수천"의 원수는 몇 개입니까? 10000? "매우 느린"속도는 어느 정도입니까? 프레임 당 100ms 이상? – genpfault

답변

1

내가 원의 수천을 렌더링하고 있기 때문에, 크기 조정 및 도면은 매우 느린 된다이 10,000 인텔 HD 그래픽 3000 프레임 당 60ms에 대해 점점 단지 정점 배열로

서클 :

// 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; 
} 
0

ARB_instanced_arrays 기반 인스 턴싱이 가장 깨끗합니다.

N 개의 그리는 M 개의 꼭지점이있는 하나의 원이 있고, 원의 x/y 위치, 반지름 및 색상을 정점 속성으로 저장하고 glVertexAttribDivisor()을 적절히 사용합니다.

반경 적응 LOD를 원할 경우 더 까다로워집니다. 이를 위해 기하 구조 셰이더를 파헤쳐 야 할 것입니다.

0

두 번째로 glDrawElementsInstanced 또는 glDrawArraysInstanced가있는 인스턴스화 된 배열을 다른 유형의 지오메트리로 잘 전달되는 깨끗한 솔루션으로 사용합니다.

예를 들어 iThing에서 실행해야하는 등의 OpenGL 2를 고수하고 싶지만 서클 만 필요하면 포인트 스프라이트도 고려하십시오. 각 원의 원점은 점 꼭지점 값입니다. 반경을 텍스처 좌표의 S 값, 표면 법선의 X 값으로 저장하십시오. 블렌딩 사용, GL_PROGRAM_POINT_SIZE, 어쩌면 포인트 스무딩; gl_PointSize를 원하는 반지름으로 설정하는 버텍스 셰이더를 작성하십시오. 즉석 서클.

관련 문제