2012-03-22 2 views
4

저는 현재 수천 개의 폴리곤을 그리는 데 OpenGL을 사용하고 있으며 매우 느리게 실행됩니다. 8000 개의 다각형을 그리려면 apx 100ms가 걸립니다. 나는 2 차원 다각형 평면의 컬렉션으로 설정 내 3D 분야에서 각 개체가많은 수의 폴리곤을 OpenGL으로 효율적으로 드로잉 할 수 있습니까?

  • , 그래서 정사각형 6, 4 정점면으로 구성 것이다 : 여기

    내 위치에 대해 몇 가지 정보입니다. 그래서 저는 각 비행기에 접근 할 수 있습니다.

    for(allPlanes){ 
        glBegin(GL_POLYGON); 
        for(allPointsInThePlane){ 
         glVertex(pointX,pointY,pointZ); 
        } 
        glEnd(); 
    } 
    

이것은 내가 기대했던 것보다 훨씬 느린 내가으로 보았다 :

  • 나는 다음과 같이 각각의 다각형 나는 현재 도면있어 정점
  • 같은 수있을 것이라는 점을 보장 할 수 없습니다 대신에 glDrawElements()를 사용하고 폴리곤 플레인을 삼각형으로 분리하고 삼각형 팬이나 스트립을 사용하여 그릴 수 있습니다.

    나는 이것을하기위한 가장 효율적인 방법에 대한 조언을 구하거나 그림에 접근하는 방식에 대한 비판을 찾고 있습니다.

  • +5

    많은 OpenGL 호출을 수행하고 있습니다. 각 호출에는 약간의 오버 헤드가 있습니다. 모든 데이터를 버퍼에 저장하고 몇 가지 호출을 사용하여 모든 것을 렌더링해야합니다. @genpfault 대답을 참조하십시오. – lvella

    답변

    9

    Triangulate 모든 것을 삼각형으로 던져 큰 VA/VBO에 던지십시오.

    편집 : GLUtesselator 래퍼 :

    struct TessContext 
    { 
        ~TessContext() 
        { 
         for(size_t i = 0; i < combined.size(); ++i) 
         { 
          delete[] combined[i]; 
         } 
        } 
    
        vector<Eigen::Vector2d> pts; 
        vector< GLdouble* > combined; 
    }; 
    
    #define APIENTRY __stdcall 
    
    void APIENTRY tess_begin(GLenum type) {} 
    void APIENTRY tess_edgeFlag(GLboolean flag) {} 
    void APIENTRY tess_end() {} 
    
    void APIENTRY tess_vertex(void *data, TessContext* ctx) 
    { 
        GLdouble* coord = (GLdouble*)data; 
        ctx->pts.push_back(Eigen::Vector2d(coord[0], coord[1])); 
    } 
    
    void APIENTRY tess_combine(GLdouble coords[3], void *vertex_data[4], GLfloat weight[4], void **outData, TessContext* ctx) 
    { 
        GLdouble* newVert = new GLdouble[3]; 
        ctx->combined.push_back(newVert); 
    
        newVert[0] = coords[0]; 
        newVert[1] = coords[1]; 
        newVert[2] = coords[2]; 
        *outData = newVert; 
    } 
    
    template< typename Vec > 
    vector<Vec> Triangulate 
        ( 
        const vector<Vec>& aSimplePolygon 
        ) 
    { 
        vector<GLdouble> coords; 
        for(size_t i = 0; i < aSimplePolygon.size(); ++i) 
        { 
         coords.push_back(aSimplePolygon[i].x()); 
         coords.push_back(aSimplePolygon[i].y()); 
         coords.push_back(0); 
        } 
    
        GLUtesselator* tess = gluNewTess(); 
        //gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); 
        //gluTessProperty(tess, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); 
    
        gluTessCallback(tess, GLU_TESS_BEGIN,   (GLvoid (APIENTRY *)()) tess_begin  ); 
        gluTessCallback(tess, GLU_TESS_EDGE_FLAG,  (GLvoid (APIENTRY *)()) tess_edgeFlag ); 
        gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (APIENTRY *)()) tess_vertex ); 
        gluTessCallback(tess, GLU_TESS_END,   (GLvoid (APIENTRY *)()) tess_end  ); 
        gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (GLvoid (APIENTRY *)()) tess_combine ); 
        gluTessNormal(tess, 0.0, 0.0, 1.0); 
    
        TessContext ctx; 
    
        gluTessBeginPolygon(tess, &ctx); 
        gluTessBeginContour(tess); 
    
        for(size_t i = 0; i < aSimplePolygon.size(); ++i) 
        { 
         gluTessVertex(tess, &coords[i*3], &coords[i*3]); 
        } 
    
        gluTessEndContour(tess); 
        gluTessEndPolygon(tess); 
    
        gluDeleteTess(tess); 
    
        vector<Vec> ret(ctx.pts.size()); 
        for(size_t i = 0; i < ret.size(); ++i) 
        { 
         ret[i].x() = ctx.pts[i].x(); 
         ret[i].y() = ctx.pts[i].y(); 
        } 
    
        return ret; 
    } 
    

    Eigen 사용하지만 흥미로운 아무것도.

    6

    glDrawArrays() 또는 glDrawElements() (또는 glDrawRangeElements())이 선호되는 방식이며 비 권장되지 않는 형식입니다. 직접 모드 (예제)는 가장 느리고 가장 선호하지 않는 방법으로 OpenGL 튜토리얼과 (내 경험상) 디버깅에 유용합니다. 또한 display lists, 그림의 직접 모드를 사용하여 위의 단 한 단계에 불과한 OpenGL의 "매크로"및 vertex buffer objects (VBOs)이 있습니다.

    직접 모드를 제외한 모든 항목이 필요에 따라 충분히 빠릅니다.

    +0

    @aid, glDrawArrays() 함수를 사용하는 데 문제가 있습니다. 각 플레인의 정점으로 사용할 수레 배열을 만듭니다. GL_VERTEX_ARRAY를 활성화 한 다음 glVerterxPointer (3, GL_FLOAT, 0, 평면 # 배열)을 각 배열에 할당합니다. 이제 각 비행기에 대한 정점 포인터가 있습니다. 그런 다음 glDrawArrays (GL_TRIANGLE_FAN, 0, ???)를 호출합니다. 마지막 매개 변수로 수행 할 작업에 대해 혼란 스럽습니다. 내가 만든 버텍스 포인터의 총 수입니까? – Dark

    +0

    세 번째 매개 변수는 그릴 꼭지점 수입니다. – aib

    2

    예 포인트를 계산하기 위해 (테셀레이션의 특별한 경우이다) 삼각를 사용하고 그들을

    현재 그래픽 아키텍처는 shaders

    을 사용하여 선호하는 방법 (당신이되지 않습니다 직접 모드를 사용)입니다 그리기

    그래서 그 대신 한 번에 모든 정점에서, 프로세서와 당신이해야 GPU 사이에 정점의 작은 집합을

    • 프로세스마다 전송하는 데이터 구조에 저장하고 g이를 보낼의 PU는

    • 전체 배열은 한 번만 계산 속도 때문이고, 데이터 유지 (glDraw *() 함수를 사용하여) 그것을 즉시 그리기 구조를 재사용 할 수 있습니다.

    • 그런 다음 추가 병없이 추가 작업을 수행 할 수있는 GPU 메모리로 데이터가 완전히 전송됩니다 데이터 전송 및 관련 오버 헤드 목 (프로그래밍 가능한 셰이더 사용)

    관련 문제