• opengl及osg中的几种渲染方法


    glDrawArrays 和 glDrawElements 的作用都是从一个数据数组中提取数据渲染基本图元。( render primitives from array data )
     
     
    注!如果要 glDrawArrays 和 glDrawElements 正确进行绘制的话,必须在之前 调用带有相应参数的 glEnableClientState 方法。 比如:

    /* Enable vertex arrays. */
    glEnableClientState( GL_VERTEX_ARRAY );
    /* Enable texture arrays. */
    glEnableClientState( GL_TEXTURE_COORD_ARRAY );


     
    这两个方法的第一个形参都是代表 绘制模式(GLenum mode)。绘图模式有如下几种:
    GL_POINTS
    GL_LINES
    GL_LINE_LOOP
    GL_LINE_STRIP
    GL_TRIANGLES
    GL_TRIANGLE_STRIP
    GL_TRIANGLE_FAN
     
    我们还没有讨论点或线,所以我只介绍最后的三个 。
    在我开始之前,我要提醒你,顶点数组可能包含不止一个三角形,以便当您只看到一个物体顶点数组,你要知道,不仅限于这一点。
     
    假设我们有如下的顶点数据:

    const GLfloat squareVertices[] = {
        -1.0,  1.0, -6.0,
    // Top left
        -1.0, -1.0, -6.0,
    // Bottom left
        1.0,  -1.0, -6.0,
    // Bottom right
        1.0,   1.0, -6.
    // Top right
    };

     
    GL_POINTS - 单独的将顶点画出来。
     
    GL_LINES - 单独地将直线画出来。行为和 GL_TRIANGLES 类似。

    GL_LINE_STRIP - 连贯地将直线画出来。行为和 GL_TRIANGLE_STRIP 类似。
     
    GL_LINE_LOOP - 连贯地将直线画出来。行为和 GL_LINE_STRIP 类似,但是会自动将最后一个顶点和第一个顶点通过直线连接起来。
     
    GL_TRIANGLES - 这个参数意味着OpenGL使用三个顶点来组成图形。所以,在开始的三个顶点,将用顶点1,顶点2,顶点3来组成一个三角形。完成后,在用下一组的三个顶点(顶点4,5,6)来组成三角形,直到数组结束。

     
    GL_TRIANGLE_STRIP - OpenGL的使用将最开始的两个顶点出发,然后遍历每个顶点,这些顶点将使用前2个顶点一起组成一个三角形。
    所以 squareVertices[6~8]{1.0, -1.0, 6.0} 将与 squareVerticies[0~2]{-1.0, 1.0, -6.0} 和 squareVerticies[3~5]{-1.0, -1.0, -6.0} 生成一个三角形。
    squareVertices[9~11]{1.0, 1,0, -6.0} 将与  squareVertices[3~5]{-1.0, -1.0, -6.0} 和squareVertices[6~8]{1.0, -1.0, 6.0} 生成三角形。
     
    也就是说,P0,P1,P2这三个点组成一个三角形,P1,P2,P3这三个点也组成一个三角形。
     
    注意的是, squareVerticies[0~2]表示的意思是:
    squareVerticies[0] x坐标
    squareVerticies[1] y坐标
    squareVerticies[2] z坐标
     
     
    GL_TRIANGLE_FAN - 在跳过开始的2个顶点,然后遍历每个顶点,让OpenGL将这些顶点于它们前一个,以及数组的第一个顶点一起组成一个三角形。 squareVertices[6~8]{1.0, -1.0, 6.0} 将与 squareVerticies[3~5]{-1.0, -1.0, -6.0} (前一个)和 squareVerticies[0~2]{-1.0, 1.0, -6.0}(第一个).生成一个三角形。
     
    也就是说,同样是P0,P1,P2,P3 这4个顶点。
    1) 在 GL_TRIANGLE_STRIP 状态下是: P2、P1、P0 ; P3、P2、P1 这2个三角形。
    2) 在 GL_TRIANGLE_FAN   状态下是: P2、P1、P0 ; P3、P2、P0 这2个三角形。
     
     
     
    1.1 glDrawArrays 方法介绍
     
    Description

    glDrawArrays specifies multiple geometric primitives with very few subroutine calls. You can prespecify separate arrays of vertices, normals, colors, and texture coordinates and use them to construct a sequence of primitives with a single call to glDrawArrays.
     
    When glDrawArrays is called, it uses count sequential elements from each enabled array to construct a sequence of geometric primitives, beginning with element first. mode specifies what kind of primitives are constructed, and how the array elements construct those primitives. If GL_VERTEX_ARRAY is not enabled, no geometric primitives are generated.
     
    Vertex attributes that are modified by glDrawArrays have an unspecified value after glDrawArrays returns. For example, if GL_COLOR_ARRAY is enabled, the value of the current color is undefined after glDrawArrays executes. Attributes that aren't modified remain well defined.


    示例代码:

    glEnableClientState(GL_VERTEX_ARRAY);
        
    const GLfixed vers[] = {
            F2X(0.25), F2X(0.25), F2X(0.0), 
            F2X(0.75), F2X(0.25), F2X(0.0), 
            F2X(0.25), F2X(0.75), F2X(0.0), 
            F2X(0.75), F2X(0.75), F2X(0.0), 
    }
    ;

    glVertexPointer(3, GL_FIXED, 0, vers);
        
    glDrawArrays(GL_LINE_STRIP, 0, 4);
        
    eglSwapBuffers(iGlDisp, iGlSurface);



    结果:

     
     
    1.2 glDrawElements 是一个OPENGL的图元绘制函数,从数组中获得数据并渲染图元。
    函数原型为:
    void glDrawElements(
            GLenum mode,
            GLsizei count,
            GLenum type,
            const GLvoid *indices
            );
    其中:
        mode 指定绘制图元的类型,但是如果GL_VERTEX_ARRAY 没有被激活的话,不能生成任何图元。它应该是下列值之一:
            GL_POINTS, GL_LINE_STRIP,
            GL_LINE_LOOP, GL_LINES,
            GL_TRIANGLE_STRIP,
            GL_TRIANGLE_FAN,
            GL_TRIANGLES,
            GL_QUAD_STRIP,
            GL_QUADS,
            GL_POLYGON

            
        count 为绘制图元的数量。
        type 为索引数组(indices)中元素的类型,只能是下列值之一:
            GL_UNSIGNED_BYTE,
            GL_UNSIGNED_SHORT,
            GL_UNSIGNED_INT

           
        indices:指向索引数组的指针。

    glDrawElements函数能够通过较少的函数调用绘制多个几何图元,而不是通过OPENGL函数调用来传递每一个顶点,法线,颜色信息。
     
    你可以事先准备一系列分离的顶点、法线、颜色数组,并且调用一次glDrawElements把这些数组定义成一个图元序列。
     
    当调用glDrawElements函数的时候,它将通过索引使用count个成序列的元素来创建一系列的几何图元。
     
    glDrawElements修改的顶点属性在glDrawElements调用返回后的值具有不确定性。

    例如,在 GL_COLOR_ARRAY 被激活后,当glDrawElements执行完成时,当前的颜色值是没有指定的。没有被修改的属性值保持不变。
     
    可以在显示列表中包含 glDrawElements,当glDrawElements被包含进显示列表时,相应的顶点、法线、颜色数组数据也得进入显示列表的,因为那些数组指针是ClientSideState的变量,在显示列表创建的时候而不是在显示列表执行的时候,这些数组指针的值影响显示列表。
     
    glDrawElements 只能用在 OPENGL1.1 或者更高的版本。

    示例代码如下:

    // The vertex array is enabled for writing and used during rendering.
    glEnableClientState(GL_VERTEX_ARRAY);

    // 顶点坐标数组
    const GLfixed vers[] = {
            F2X(0.25), F2X(0.25), F2X(0.0),
    // 第1个顶点坐标
            F2X(0.75), F2X(0.25), F2X(0.0),
    // 第2个顶点坐标
            F2X(0.25), F2X(0.75), F2X(0.0),
    // 第3个顶点坐标
            F2X(0.75), F2X(0.75), F2X(0.0) 
    // 第4个顶点坐标
    };


    glVertexPointer(
            3,        
    // 表示每一个顶点由3维坐标构成
            GL_FIXED,
    // 顶点坐标数组中的元素是 GL_FIXED 类型
            0,       
    // 从顶点坐标数组的第0个元素开始读取数据
            vers      
    // 指向顶点坐标数组的指针
            );

    // 等效替换 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) ++

    /* 索引数组. 此索引数组表示依次是
    第0个顶点{F2X(0.25), F2X(0.25), F2X(0.0)},
    第1个顶点{F2X(0.75), F2X(0.25), F2X(0.0)},
    第2个顶点{F2X(0.25), F2X(0.75), F2X(0.0)},
    第3个顶点{F2X(0.75), F2X(0.75), F2X(0.0)} */

    const GLubyte indices[] = {0, 1, 2, 3};

    glDrawElements(
            GL_TRIANGLE_STRIP,
    // 绘图模式
            4,                
    // 依次从索引数组中读取4个顶点来进行绘制
            GL_UNSIGNED_BYTE, 
    // 索引数组中存放的元素的类型
            indices           
    // 指向索引数组的指针
            );

    // 等效替换 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) --


    eglSwapBuffers(iGlDisp, iGlSurface);

     

    OpenGL VBO并不难,但是较繁琐,其实其概念跟加载纹理是一样的:

    初始化阶段:
    1. glGenBuffersARB(1, &nVBOVertices); //生成一个句柄
    2. glBindBufferARB(GL_ARRAY_BUFFER_ARB, nVBOVertices); //声明该句柄为一个vbo句柄,并选择之
    3. glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices), vertices,GL_STATIC_DRAW); //将顶点集上传至server端

    使用阶段:
    1. glEnableClientState(GL_VERTEX_ARRAY); //开始使用vbo
    2. glBindBufferARB(GL_ARRAY_BUFFER_ARB, nVBOVertices);  //选择当前使用的vbo
    3. glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));  //指定vbo顶点格式
    4. glDrawArrays( GL_TRIANGLES, 0, g_pMesh->m_nVertexCount ); //画吧
    5. glDisableClientState(GL_VERTEX_ARRAY); //停止使用vbo

    收尾阶段:
    1. glDeleteBuffersARB(1,&nVBOVertices); //删除句柄,同时删除server端顶点缓冲

    再来看看纹理缓冲是怎么使用的,其实差不多:

    初始化阶段:
    1. glGenTextures(1, &texID);//创建句柄
    2. glBindTexture(GL_TEXTURE_2D, texID); //设置句柄类型
    3. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->GetWidth(), img->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, raw_rgba); //上传纹理缓冲

    使用阶段:
    1. glEnable(GL_TEXTURE_2D); //开始使用纹理缓冲
    2. glBindTexture(GL_TEXTURE_2D, texID); //选择当前使用的纹理缓冲
    3. 发送顶点和纹理坐标,画吧...省略
    4. glDisable(GL_TEXTURE_2D); //停止使用纹理

    收尾阶段:
    1. glDeleteTextures(1,&texID);//删除句柄,,同时删除server端缓冲

    看到了么,这个概念是不是很相似?都是:

    1. 创建句柄
    2. 设置句柄类型
    3. 上传数据
    4. 开始使用缓冲
    5. 选择句柄
    6. 使用缓冲
    7. 停止使用缓冲
    8. 删除句柄和缓冲

     

     

     

     

    void Geometry::drawImplementation(RenderInfo& renderInfo) const
    {
        State& state = *renderInfo.getState();

    //    unsigned int contextID = state.getContextID();
       
        // osg::notify(osg::NOTICE)<<"Geometry::drawImplementation"<<std::endl;

        if (_internalOptimizedGeometry.valid())
        {
            _internalOptimizedGeometry->drawImplementation(renderInfo);
            return;
        }

        const Extensions* extensions = getExtensions(state.getContextID(),true);

        if( !( ( _vertexData.array.valid() && _vertexData.array->getNumElements() != 0 ) ||
               ( _vertexAttribList.size() > 0 &&
                 _vertexAttribList[0].array.valid() &&
                 _vertexAttribList[0].array->getNumElements() != 0 ) ) )
        {
            return;
        }

        if( ( _vertexData.indices.valid() && _vertexData.indices->getNumElements() == 0 ) ||
              ( _vertexAttribList.size() > 0 &&
              _vertexAttribList[0].indices.valid() &&
              _vertexAttribList[0].indices->getNumElements() == 0 ) )
        {
            return;
        }

        DrawNormal         drawNormal(_normalData.array.get(),_normalData.indices.get());
        DrawColor          drawColor(_colorData.array.get(),_colorData.indices.get());
        DrawSecondaryColor drawSecondaryColor(_secondaryColorData.array.get(),_secondaryColorData.indices.get(),extensions);

        DrawFogCoord       drawFogCoord(_fogCoordData.array.get(),_fogCoordData.indices.get(),extensions);


        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //
        // Set up secondary color if required.
        //
        AttributeBinding secondaryColorBinding = _secondaryColorData.binding;
        if (secondaryColorBinding!=BIND_OFF && !extensions->isSecondaryColorSupported())
        {
            // switch off if not supported or have a valid data.
            secondaryColorBinding = BIND_OFF;
        }

       
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //
        // Set up fog coord if required.
        //
        AttributeBinding fogCoordBinding = _fogCoordData.binding;
        if (fogCoordBinding!=BIND_OFF && !extensions->isFogCoordSupported())
        {
            // switch off if not supported or have a valid data.
            fogCoordBinding = BIND_OFF;
        }

        unsigned int normalIndex = 0;
        unsigned int colorIndex = 0;
        unsigned int secondaryColorIndex = 0;
        unsigned int fogCoordIndex = 0;

    #if USE_DEFAULT_NORMAL
        // if no values are defined for normal and color provide some defaults...
        if (_normalData.binding==BIND_OFF) glNormal3f(0.0f,0.0f,1.0f);
    #endif

    #if USE_DEFAULT_COLOUR
        if (_colorData.binding==BIND_OFF) glColor4f(1.0f,1.0f,1.0f,1.0f);
    #endif

        typedef std::vector< ref_ptr<DrawVertexAttrib> > DrawVertexAttribList;
        typedef std::map< Geometry::AttributeBinding, DrawVertexAttribList> DrawVertexAttribMap;
        DrawVertexAttribMap drawVertexAttribMap;
       
        bool vertexVertexAttributesSupported = extensions->isVertexProgramSupported();
        bool handleVertexAttributes = (!_vertexAttribList.empty() && vertexVertexAttributesSupported);

        bool usingVertexBufferObjects = _useVertexBufferObjects && state.isVertexBufferObjectSupported();
       
        if (areFastPathsUsed())
        {
       
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // fast path.       
            //
            if (usingVertexBufferObjects)     //用顶点缓冲区
            {

                //
                // Vertex Buffer Object path for defining vertex arrays.
                //
                state.setNormalPointer(_normalData.binding==BIND_PER_VERTEX ? _normalData.array.get() : 0);
                state.setColorPointer(_colorData.binding==BIND_PER_VERTEX ? _colorData.array.get() : 0);
                state.setSecondaryColorPointer(_secondaryColorData.binding==BIND_PER_VERTEX ? _secondaryColorData.array.get() : 0);
                state.setFogCoordPointer(_fogCoordData.binding==BIND_PER_VERTEX ? _fogCoordData.array.get() : 0);

                unsigned int unit;
                for(unit=0;unit<_texCoordList.size();++unit)
                {
                    state.setTexCoordPointer(unit, _texCoordList[unit].array.get());
                }
                state.disableTexCoordPointersAboveAndIncluding(unit);

                if( handleVertexAttributes )
                {
                    unsigned int index;
                    for( index = 0; index < _vertexAttribList.size(); ++index )
                    {
                        const Array* array = _vertexAttribList[index].array.get();
                        const AttributeBinding ab = _vertexAttribList[index].binding;
                        state.setVertexAttribPointer(index, (ab==BIND_PER_VERTEX ? array : 0), _vertexAttribList[index].normalize);

                        if(array && ab!=BIND_PER_VERTEX)
                        {
                            const IndexArray* indexArray = _vertexAttribList[index].indices.get();

                            if( indexArray && indexArray->getNumElements() > 0 )
                            {
                                drawVertexAttribMap[ab].push_back(
                                    new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,indexArray) );
                            }
                            else
                            {
                                drawVertexAttribMap[ab].push_back(
                                    new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,0) );
                            }
                        }
                    }
                    state.disableVertexAttribPointersAboveAndIncluding( index );
                   
                }
                else if (vertexVertexAttributesSupported)
                {
                    state.disableVertexAttribPointersAboveAndIncluding( 0 );
                }

                state.setVertexPointer(_vertexData.array.get());//传入顶点数组及指针


            }
            else
            {
                //std::cout << "none VertexBuffer path"<<std::endl;

                //
                // Non Vertex Buffer Object path for defining vertex arrays.
                //           
                if( _vertexData.array.valid() )
                    state.setVertexPointer(_vertexData.array->getDataSize(),_vertexData.array->getDataType(),0,_vertexData.array->getDataPointer());
                else
                    state.disableVertexPointer();

                if (_normalData.binding==BIND_PER_VERTEX && _normalData.array.valid())
                    state.setNormalPointer(_normalData.array->getDataType(),0,_normalData.array->getDataPointer());
                else
                    state.disableNormalPointer();

                if (_colorData.binding==BIND_PER_VERTEX && _colorData.array.valid())
                    state.setColorPointer(_colorData.array->getDataSize(),_colorData.array->getDataType(),0,_colorData.array->getDataPointer());
                else
                    state.disableColorPointer();

                if (secondaryColorBinding==BIND_PER_VERTEX && _secondaryColorData.array.valid())
                    state.setSecondaryColorPointer(_secondaryColorData.array->getDataSize(),_secondaryColorData.array->getDataType(),0,_secondaryColorData.array->getDataPointer());
                else
                    state.disableSecondaryColorPointer();

                if (fogCoordBinding==BIND_PER_VERTEX && _fogCoordData.array.valid())
                    state.setFogCoordPointer(GL_FLOAT,0,_fogCoordData.array->getDataPointer());
                else
                    state.disableFogCoordPointer();

                unsigned int unit;
                for(unit=0;unit<_texCoordList.size();++unit)
                {
                    const Array* array = _texCoordList[unit].array.get();
                    if (array)
                        state.setTexCoordPointer(unit,array->getDataSize(),array->getDataType(),0,array->getDataPointer());
                    else
                        state.disableTexCoordPointer(unit);
                }
                state.disableTexCoordPointersAboveAndIncluding(unit);

                if( handleVertexAttributes )
                {
                    unsigned int index;
                    for( index = 0; index < _vertexAttribList.size(); ++index )
                    {
                        const Array* array = _vertexAttribList[index].array.get();
                        const AttributeBinding ab = _vertexAttribList[index].binding;

                        if( ab == BIND_PER_VERTEX && array )
                        {
                            state.setVertexAttribPointer( index, array->getDataSize(), array->getDataType(),
                                _vertexAttribList[index].normalize, 0, array->getDataPointer() );
                        }
                        else
                        {
                            if( array )
                            {
                                const IndexArray* indexArray = _vertexAttribList[index].indices.get();

                                if( indexArray && indexArray->getNumElements() > 0 )
                                {
                                    drawVertexAttribMap[ab].push_back(
                                        new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,indexArray) );
                                }
                                else
                                {
                                    drawVertexAttribMap[ab].push_back(
                                        new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,0) );
                                }
                            }

                            state.disableVertexAttribPointer( index );
                        }
                    }
                    state.disableVertexAttribPointersAboveAndIncluding( index );
                   
                }
                else if (vertexVertexAttributesSupported)
                {
                    state.disableVertexAttribPointersAboveAndIncluding( 0 );
                }
            }
           
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // pass the overall binding values onto OpenGL.
            //
            if (_normalData.binding==BIND_OVERALL)      drawNormal(normalIndex++);
            if (_colorData.binding==BIND_OVERALL)       drawColor(colorIndex++);
            if (secondaryColorBinding==BIND_OVERALL)    drawSecondaryColor(secondaryColorIndex++);
            if (fogCoordBinding==BIND_OVERALL)          drawFogCoord(fogCoordIndex++);
            if (handleVertexAttributes)
            {
                DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL];

                for( unsigned int i = 0; i < list.size(); ++i )
                {
                    list[i]->applyAndIncrement();
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // draw the primitives themselves.
            //
            for(PrimitiveSetList::const_iterator itr=_primitives.begin();
                itr!=_primitives.end();
                ++itr)
            {

                if (_normalData.binding==BIND_PER_PRIMITIVE_SET)      drawNormal(normalIndex++);
                if (_colorData.binding==BIND_PER_PRIMITIVE_SET)       drawColor(colorIndex++);
                if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET)    drawSecondaryColor(secondaryColorIndex++);
                if (fogCoordBinding==BIND_PER_PRIMITIVE_SET)          drawFogCoord(fogCoordIndex++);
                if (handleVertexAttributes)
                {
                    DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET];

                    for( unsigned int i = 0; i < list.size(); ++i )
                    {
                        list[i]->applyAndIncrement();
                    }
                }

                (*itr)->draw(state, usingVertexBufferObjects);//内部生成顶点纹理索引,并绑定画图

            }

            if (usingVertexBufferObjects)
            {
    #if 1
                state.unbindVertexBufferObject();
                state.unbindElementBufferObject();
    #endif
            }

        }
        else
        {  

            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // slow path.       
            //
           

            typedef std::vector< ref_ptr<DrawMultiTexCoord> > DrawTexCoordList;
            DrawTexCoordList drawTexCoordList;
            drawTexCoordList.reserve(_texCoordList.size());

            // fallback if multitexturing not supported.
            ref_ptr<DrawTexCoord> drawTextCoord;

            if (extensions->isMultiTexSupported() && _texCoordList.size()>1)
            {
                // multitexture supported..
                for(unsigned int unit=0;unit!=_texCoordList.size();++unit)
                {
                    const ArrayData& texcoordData = _texCoordList[unit];
                    if (texcoordData.array.valid() && texcoordData.array->getNumElements()>0)
                    {
                        if (texcoordData.indices.valid() && texcoordData.indices->getNumElements()>0)
                        {
                            drawTexCoordList.push_back(new DrawMultiTexCoord(GL_TEXTURE0+unit,texcoordData.array.get(),texcoordData.indices.get(),
                                                                             extensions));
                        }
                        else
                        {
                            drawTexCoordList.push_back(new DrawMultiTexCoord(GL_TEXTURE0+unit,texcoordData.array.get(),0,
                                                                              extensions));
                        }
                    }
                }
            }
            else
            {
                if (!_texCoordList.empty())
                {
                    const ArrayData& texcoordData = _texCoordList[0];
                    if (texcoordData.array.valid() && texcoordData.array->getNumElements()>0)
                    {
                        if (texcoordData.indices.valid())
                        {
                            if (texcoordData.indices->getNumElements()>0)
                            {
                                drawTextCoord = new DrawTexCoord(texcoordData.array.get(),texcoordData.indices.get());
                            }
                        }
                        else
                        {
                            drawTextCoord = new DrawTexCoord(texcoordData.array.get(),0);
                        }
                    }
                }
            }

            if(handleVertexAttributes)
            {
                unsigned int index;
                for( index = 1; index < _vertexAttribList.size(); ++index )
                {
                    const ArrayData& vertAttribData = _vertexAttribList[index];
               
                    if( vertAttribData.array.valid() && vertAttribData.array->getNumElements() > 0 )
                    {
                        if( vertAttribData.indices.valid() && vertAttribData.indices->getNumElements() > 0 )
                        {
                            drawVertexAttribMap[vertAttribData.binding].push_back(
                                new DrawVertexAttrib(extensions,index,vertAttribData.normalize,vertAttribData.array.get(),vertAttribData.indices.get() ));
                        }
                        else
                        {
                            drawVertexAttribMap[vertAttribData.binding].push_back(
                                new DrawVertexAttrib(extensions,index,vertAttribData.normalize,vertAttribData.array.get(),0) );
                        }           
                    }
                }
            }

            // disable all the vertex arrays in the slow path as we are
            // sending everything using glVertex etc.
            state.disableAllVertexArrays();


            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // pass the overall binding values onto OpenGL.
            //
            if (_normalData.binding==BIND_OVERALL)      drawNormal(normalIndex++);
            if (_colorData.binding==BIND_OVERALL)       drawColor(colorIndex++);
            if (secondaryColorBinding==BIND_OVERALL)    drawSecondaryColor(secondaryColorIndex++);
            if (fogCoordBinding==BIND_OVERALL)          drawFogCoord(fogCoordIndex++);
            if (handleVertexAttributes)
            {
                DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL];

                for( unsigned int i = 0; i < list.size(); ++i )
                {
                    list[i]->applyAndIncrement();
                }
            }

            // set up vertex functor.
            DrawVertex drawVertex(_vertexData.array.get(),_vertexData.indices.get());

            bool useVertexAttrib =  _vertexAttribList.size() > 0 &&
                                    _vertexAttribList[0].array.valid() &&
                                     _vertexAttribList[0].indices->getNumElements();

            ref_ptr<DrawVertexAttrib> drawVertexAttribZero;
            if( useVertexAttrib )
            {
                drawVertexAttribZero = new DrawVertexAttrib(extensions,0,
                    _vertexAttribList[0].normalize,_vertexAttribList[0].array.get(),
                    _vertexAttribList[0].indices.get());
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //
            // draw the primitives themselves.
            //
            for(PrimitiveSetList::const_iterator itr=_primitives.begin();
                itr!=_primitives.end();
                ++itr)
            {
                if (_normalData.binding==BIND_PER_PRIMITIVE_SET)           drawNormal(normalIndex++);
                if (_colorData.binding==BIND_PER_PRIMITIVE_SET)            drawColor(colorIndex++);
                if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET)    drawSecondaryColor(secondaryColorIndex++);
                if (fogCoordBinding==BIND_PER_PRIMITIVE_SET)          drawFogCoord(fogCoordIndex++);
                if (handleVertexAttributes)
                {
                    DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET];

                    for( unsigned int i = 0; i < list.size(); ++i )
                    {
                        list[i]->applyAndIncrement();
                    }
                }

                const PrimitiveSet* primitiveset = itr->get();
                GLenum mode=primitiveset->getMode();

                unsigned int primLength;
                switch(mode)
                {
                    case(GL_POINTS):    primLength=1; break;
                    case(GL_LINES):     primLength=2; break;
                    case(GL_TRIANGLES): primLength=3; break;
                    case(GL_QUADS):     primLength=4; break;
                    default:            primLength=0; break; // compute later when =0.
                }


                // draw primitives by the more flexible "slow" path,
                // sending OpenGL glBegin/glVertex.../glEnd().
                switch(primitiveset->getType())                  //glBegin()及glEnd()画图
                {
                    case(PrimitiveSet::DrawArraysPrimitiveType):
                    {
                        if (primLength==0) primLength=primitiveset->getNumIndices();

                        const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
                        glBegin(mode);

                        unsigned int primCount=0;
                        unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
                        for(unsigned int vindex=drawArray->getFirst();
                            vindex<indexEnd;
                            ++vindex,++primCount)
                        {

                            if ((primCount%primLength)==0)
                            {
                                if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
                                if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
                                if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
                                if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
                                if (handleVertexAttributes)
                                {
                                    DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];

                                    for( unsigned int i = 0; i < list.size(); ++i )
                                    {
                                        list[i]->applyAndIncrement();
                                    }
                                }                       
                            }

                            if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
                            if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
                            if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
                            if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
                            if (handleVertexAttributes)
                            {
                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];

                                for( unsigned int i = 0; i < list.size(); ++i )
                                {
                                    list[i]->applyAndIncrement();
                                }
                            } 

                            for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
                                texItr!=drawTexCoordList.end();
                                ++texItr)
                            {
                                (*(*texItr))(vindex);
                            }
                            if (drawTextCoord.valid()) (*drawTextCoord)(vindex);

                            if( useVertexAttrib )
                            {
                                (*drawVertexAttribZero)(vindex);
                            }
                            else
                            {
                                drawVertex(vindex);
                            }
                        }
                       
                        glEnd();
                        break;
                    }
                    case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
                    {

                        const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
                        unsigned int vindex=drawArrayLengths->getFirst();
                        for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
                            primItr!=drawArrayLengths->end();
                            ++primItr)
                        {
                            unsigned int localPrimLength;
                            if (primLength==0) localPrimLength=*primItr;
                            else localPrimLength=primLength;

                            glBegin(mode);

                            for(GLsizei primCount=0;primCount<*primItr;++primCount)
                            {
                                if ((primCount%localPrimLength)==0)
                                {
                                    if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
                                    if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
                                    if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
                                    if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
                                    if (handleVertexAttributes)
                                    {
                                        DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];

                                        for( unsigned int i = 0; i < list.size(); ++i )
                                        {
                                            list[i]->applyAndIncrement();
                                        }
                                    } 
                                }
                               
                                if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
                                if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
                                if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
                                if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
                                if (handleVertexAttributes)
                                {
                                    DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];

                                    for( unsigned int i = 0; i < list.size(); ++i )
                                    {
                                        list[i]->applyAndIncrement();
                                    }
                                } 
                                for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
                                    texItr!=drawTexCoordList.end();
                                    ++texItr)
                                {
                                    (*(*texItr))(vindex);
                                }
                                if (drawTextCoord.valid()) (*drawTextCoord)(vindex);

                                if( useVertexAttrib )
                                {
                                    (*drawVertexAttribZero)(vindex);
                                }
                                else
                                {
                                    drawVertex(vindex);
                                }

                                ++vindex;
                            }
                           
                            glEnd();

                        }
                        break;
                    }
                    case(PrimitiveSet::DrawElementsUBytePrimitiveType):
                    {
                        if (primLength==0) primLength=primitiveset->getNumIndices();

                        const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
                        glBegin(mode);

                        unsigned int primCount=0;
                        for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
                            primItr!=drawElements->end();
                            ++primCount,++primItr)
                        {

                            if ((primCount%primLength)==0)
                            {
                                if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
                                if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
                                if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
                                if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
                                if (handleVertexAttributes)
                                {
                                    DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];

                                    for( unsigned int i = 0; i < list.size(); ++i )
                                    {
                                        list[i]->applyAndIncrement();
                                    }
                                } 
                            }
                           
                            unsigned int vindex=*primItr;

                            if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
                            if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
                            if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
                            if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
                            if ( extensions->isVertexProgramSupported() )
                            {
                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];

                                for( unsigned int i = 0; i < list.size(); ++i )
                                {
                                    list[i]->applyAndIncrement();
                                }
                            } 

                            for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
                                texItr!=drawTexCoordList.end();
                                ++texItr)
                            {
                                (*(*texItr))(vindex);
                            }
                            if (drawTextCoord.valid()) (*drawTextCoord)(vindex);

                            if( useVertexAttrib )
                            {
                                (*drawVertexAttribZero)(vindex);
                            }
                            else
                            {
                                drawVertex(vindex);
                            }
                        }

                        glEnd();
                        break;
                    }
                    case(PrimitiveSet::DrawElementsUShortPrimitiveType):
                    {
                        if (primLength==0) primLength=primitiveset->getNumIndices();

                        const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
                        glBegin(mode);

                        unsigned int primCount=0;
                        for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
                            primItr!=drawElements->end();
                            ++primCount,++primItr)
                        {

                            if ((primCount%primLength)==0)
                            {
                                if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
                                if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
                                if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
                                if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
                                if (handleVertexAttributes)
                                {
                                    DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];

                                    for( unsigned int i = 0; i < list.size(); ++i )
                                    {
                                        list[i]->applyAndIncrement();
                                    }
                                } 
                            }
                           
                            unsigned int vindex=*primItr;

                            if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
                            if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
                            if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
                            if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
                            if (handleVertexAttributes)
                            {
                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];

                                for( unsigned int i = 0; i < list.size(); ++i )
                                {
                                    list[i]->applyAndIncrement();
                                }
                            } 

                            for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
                                texItr!=drawTexCoordList.end();
                                ++texItr)
                            {
                                (*(*texItr))(vindex);
                            }
                            if (drawTextCoord.valid()) (*drawTextCoord)(vindex);

                            if( useVertexAttrib )
                            {
                                (*drawVertexAttribZero)(vindex);
                            }
                            else
                            {
                                drawVertex(vindex);
                            }
                        }

                        glEnd();
                        break;
                    }
                    case(PrimitiveSet::DrawElementsUIntPrimitiveType):
                    {
                        if (primLength==0) primLength=primitiveset->getNumIndices();

                        const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
                        glBegin(mode);

                        unsigned int primCount=0;
                        for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
                            primItr!=drawElements->end();
                            ++primCount,++primItr)
                        {

                            if ((primCount%primLength)==0)
                            {
                                if (_normalData.binding==BIND_PER_PRIMITIVE)           drawNormal(normalIndex++);
                                if (_colorData.binding==BIND_PER_PRIMITIVE)            drawColor(colorIndex++);
                                if (secondaryColorBinding==BIND_PER_PRIMITIVE)    drawSecondaryColor(secondaryColorIndex++);
                                if (fogCoordBinding==BIND_PER_PRIMITIVE)          drawFogCoord(fogCoordIndex++);
                                if ( extensions->isVertexProgramSupported() )
                                {
                                    DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE];

                                    for( unsigned int i = 0; i < list.size(); ++i )
                                    {
                                        list[i]->applyAndIncrement();
                                    }
                                } 
                            }
                           
                            unsigned int vindex=*primItr;

                            if (_normalData.binding==BIND_PER_VERTEX)           drawNormal(vindex);
                            if (_colorData.binding==BIND_PER_VERTEX)            drawColor(vindex);
                            if (secondaryColorBinding==BIND_PER_VERTEX)    drawSecondaryColor(vindex);
                            if (fogCoordBinding==BIND_PER_VERTEX)          drawFogCoord(vindex);
                            if ( extensions->isVertexProgramSupported() )
                            {
                                DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX];

                                for( unsigned int i = 0; i < list.size(); ++i )
                                {
                                    list[i]->applyAndIncrement();
                                }
                            } 

                            for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin();
                                texItr!=drawTexCoordList.end();
                                ++texItr)
                            {
                                (*(*texItr))(vindex);
                            }
                            if (drawTextCoord.valid()) (*drawTextCoord)(vindex);

                            if( useVertexAttrib )
                            {
                                (*drawVertexAttribZero)(vindex);
                            }
                            else
                            {
                                drawVertex(vindex);
                            }
                        }

                        glEnd();
                        break;
                    }
                    default:
                    {
                        break;
                    }
                }
            }
        }

    }



  • 相关阅读:
    【uniapp】改善中大型uniapp小程序项目开发体验
    vite试玩:老项目启动从6分钟到秒开
    修剪AST树减少webapck打包尺寸
    librispeech数据集下载
    语音识别性能评估方法
    2021.12.11 物联网考试
    2021.12.15 课程总结+加分项
    2021.12.9 观影大数据分析
    2021.12.8 Docker服务
    2021.12.10 阿里云服务器创建
  • 原文地址:https://www.cnblogs.com/lizhengjin/p/1839646.html
Copyright © 2020-2023  润新知