Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用OpenGL高效地绘制大量多边形?_Opengl - Fatal编程技术网

使用OpenGL高效地绘制大量多边形?

使用OpenGL高效地绘制大量多边形?,opengl,Opengl,我目前正在使用opengl绘制数千个多边形,而且速度非常慢。绘制8000个多边形需要apx 100毫秒 以下是有关我的设置的一些信息: 我将三维场中的每个对象设置为二维多边形平面的集合,因此正方形将由6个、4个顶点平面组成。所以我可以访问每架飞机 我不能保证每个多边形都有相同数量的顶点 我目前正在绘制如下图: for(allPlanes){ glBegin(GL_POLYGON); for(allPointsInThePlane){ glVertex(pointX,po

我目前正在使用opengl绘制数千个多边形,而且速度非常慢。绘制8000个多边形需要apx 100毫秒

以下是有关我的设置的一些信息:

  • 我将三维场中的每个对象设置为二维多边形平面的集合,因此正方形将由6个、4个顶点平面组成。所以我可以访问每架飞机
  • 我不能保证每个多边形都有相同数量的顶点
  • 我目前正在绘制如下图:

    for(allPlanes){
      glBegin(GL_POLYGON);
       for(allPointsInThePlane){
           glVertex(pointX,pointY,pointZ);
        }
      glEnd();
    }
    
这比我预期的要慢得多,我已经研究过使用glDrawerElements()来代替,并将多边形平面分解为三角形,然后使用三角形或条带来绘制它们

我只是想找一些关于最有效的方法的建议,或者对我画画的方法的任何批评。

把所有的东西都扔进一个大的三角形里

编辑:面筋研磨机包装:

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;
}
struct-context
{
~TessContext()
{
对于(size_t i=0;ipts;
向量组合;
};
#定义APIENTRY\uu stdcall
void-apitery-tess_-begin(盂型){}
void apitery tess_edgeFlag(GLboolean标志){}
void apitery tess_end(){}
void apitery tess_顶点(void*数据,TessContext*ctx)
{
GLdouble*坐标=(GLdouble*)数据;
ctx->pts.push_back(本征::矢量2D(坐标[0],坐标[1]);
}
void apitery tess_combine(GLdouble coords[3],void*顶点_数据[4],GLfloat weight[4],void**outData,TessContext*ctx)
{
GLdouble*newVert=新GLdouble[3];
ctx->组合。推回(newVert);
newVert[0]=coords[0];
newVert[1]=coords[1];
newVert[2]=coords[2];
*outData=newVert;
}
模板
向量三角化
( 
常量向量&简单多边形
)
{
向量坐标;
对于(size_t i=0;iret(ctx.pts.size());
对于(大小i=0;i
使用,但不用于任何有趣的东西。

或(或)是首选方式,也是唯一未弃用的方式。即时模式(您的示例)是最慢和最不受欢迎的方法,主要用于OpenGL教程和(根据我自己的经验)调试。还有
显示列表
,“宏”用于OpenGL,仅比使用即时模式进行绘图高一步,以及
顶点缓冲区对象(VBO)

除立即模式外,任何其他模式都应足够快,以满足您的需要

是的,使用三角剖分(这是细分的一种特殊情况)来计算点,然后绘制它们是首选方式(您使用了不推荐使用的立即模式)

当前的图形体系结构使用

因此,与每次在处理器和GPU之间发送一小组顶点不同,您应该

  • 一次处理所有顶点,将其保存到数据结构并发送到gpu

  • 立即绘制(使用glDraw*()函数)

这会更快,因为

  • 整个数组只计算一次,并保留在数据结构中,以便重用

  • 然后,数据被完全发送到GPU内存,在那里可以执行进一步的操作,而无需任何额外的数据传输瓶颈和相关开销(通过使用可编程着色器)


您正在进行大量OpenGL调用。每次通话都会有一些开销,是什么让事情变得缓慢。您必须将所有数据存储在缓冲区中,并且只需使用几个调用即可呈现所有内容。请参阅@genpfault-answer@aid,我在尝试使用glDrawArrays()函数时遇到了问题。我创建一个浮动数组,用作每个平面的顶点。我启用GL_VERTEX_数组,然后为每个数组分配一个glVerterxPointer(3,GL_FLOAT,0,plane#ARRAY)。现在我的每个平面都有一个顶点指针。然后我调用gldrawArray(GL_TRIANGLE_FAN,0,?),我不知道如何处理最后一个参数,它是我制作的顶点指针总数吗?第三个参数是要绘制的顶点数。