MyGui笔记(4)渲染过程

前篇:《MyGui笔记(3)控件对齐方式和所在层》
本篇:记录下渲染的过程。
环境:MyGui3.2.0(OpenGL平台)

        MyGui的渲染过程比较复杂,这里仅记录一下一些要点,如有错误的地方,还请指出。在第一篇有提到在BaseManager::run函数里面进行每一帧的绘制,调用的是drawOneFrame()方法,这个方法代码如下: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void BaseManager::drawOneFrame()
{
     // First we clear the screen and depth buffer
     // 首先清除屏幕和深度缓冲
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     // Then we reset the modelview matrix
     // 然后重置模型视图矩阵
    glLoadIdentity();

     if (mPlatform)
        mPlatform->getRenderManagerPtr()->drawOneFrame();

    SwapBuffers(hDC);
}

调用的是OpenGLRenderManagerdrawOneFrame()方法,代码如下: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void OpenGLRenderManager::drawOneFrame()
{
    Gui* gui = Gui::getInstancePtr();
     if (gui == nullptr)
         return;

     static Timer timer;
     static  unsigned  long last_time = timer.getMilliseconds();
     unsigned  long now_time = timer.getMilliseconds();
     unsigned  long time = now_time - last_time;

    onFrameEvent(( float)(( double)(time) / ( double) 1000));

    last_time = now_time;

    begin();
    onRenderToTarget( this, mUpdate);
    end();

    mUpdate =  false;
}

在这里进行每一帧事件的触发,和每一帧的渲染,渲染调用其onRenderToTarget方法,代码如下: 

1
2
3
4
5
6
void RenderManager::onRenderToTarget(IRenderTarget* _target,  bool _update)
{
    LayerManager* layers = LayerManager::getInstancePtr();
     if (layers != nullptr)
        layers->renderToTarget(_target, _update);
}

可以看到在这里调用的是LayerManager层管理器来进行绘制,具体代码如下: 

1
2
3
4
5
6
7
void LayerManager::renderToTarget(IRenderTarget* _target,  bool _update)
{
     for (VectorLayer::iterator iter = mLayerNodes.begin(); iter != mLayerNodes.end(); ++iter)
    {
        (*iter)->renderToTarget(_target, _update);
    }
}

mLayerNodes里的所有层依次进行调用渲染,故定义在MyGUI_Layers.xml文件最上面的层,将会最先开始渲染,顺序如Wallpaper→Back→Overlapped→……。具体的渲染方法是根据不同的层类型来进行的,代码分别如下: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void SharedLayer::renderToTarget(IRenderTarget* _target,  bool _update)
{
     if (mChildItem != nullptr)
        mChildItem->renderToTarget(_target, _update);

    mOutOfDate =  false;
}

void OverlappedLayer::renderToTarget(IRenderTarget* _target,  bool _update)
{
     for (VectorILayerNode::iterator iter = mChildItems.begin(); iter != mChildItems.end(); ++iter)
        (*iter)->renderToTarget(_target, _update);

    mOutOfDate =  false;
}

在这里可以看到SharedLayer只进行了一次渲染,而OverlappedLayer对附加的根控件节点依次进行渲染,最终调用的都是LayerNode::renderToTarget方法,代码如下: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void LayerNode::renderToTarget(IRenderTarget* _target,  bool _update)
{
    mDepth = _target->getInfo().maximumDepth;

     // 检查压缩空隙
     bool need_compression =  false;
     for (VectorRenderItem::iterator iter = mFirstRenderItems.begin(); iter != mFirstRenderItems.end(); ++iter)
    {
         if ((*iter)->getCompression())
        {
            need_compression =  true;
             break;
        }
    }

     if (need_compression)
        updateCompression();

     // 首先渲染
     for (VectorRenderItem::iterator iter = mFirstRenderItems.begin(); iter != mFirstRenderItems.end(); ++iter)
        (*iter)->renderToTarget(_target, _update);

     for (VectorRenderItem::iterator iter = mSecondRenderItems.begin(); iter != mSecondRenderItems.end(); ++iter)
        (*iter)->renderToTarget(_target, _update);

     // 现在绘制子节点
     for (VectorILayerNode::iterator iter = mChildItems.begin(); iter != mChildItems.end(); ++iter)
        (*iter)->renderToTarget(_target, _update);

    mOutOfDate =  false;
}

渲染调用的方法为RenderItem::renderToTarget,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
void RenderItem::renderToTarget(IRenderTarget* _target,  bool _update)
{
     if (mTexture == nullptr)
         return;

    mRenderTarget = _target;

    mCurrentUpdate = _update;

     if (mOutOfDate || _update)
    {
        mCountVertex =  0;
        Vertex* buffer = mVertexBuffer->lock();
         if (buffer != nullptr)
        {
             for (VectorDrawItem::iterator iter = mDrawItems.begin(); iter != mDrawItems.end(); ++iter)
            {
                 // 在调用之前记住缓冲区的位置
                mCurrentVertex = buffer;
                mLastVertexCount =  0;

                (*iter).first->doRender();

                 // 数量惊人的顶点绘制
                MYGUI_DEBUG_ASSERT(mLastVertexCount <= (*iter).second,  "It is too much vertexes");
                buffer += mLastVertexCount;
                mCountVertex += mLastVertexCount;
            }

            mVertexBuffer->unlock();
        }

        mOutOfDate =  false;
    }

     // 虽然0不是批次显示,但它仍然不会产生状态和操作
     if ( 0 != mCountVertex)
    {
#if MYGUI_DEBUG_MODE ==  1
         if (!RenderManager::getInstance().checkTexture(mTexture))
        {
            mTexture = nullptr;
            MYGUI_EXCEPT( "texture pointer is not valid, texture name '" << mTextureName <<  "'");
             return;
        }
#endif
         //直接渲染
         if (mManualRender)
        {
             for (VectorDrawItem::iterator iter = mDrawItems.begin(); iter != mDrawItems.end(); ++iter)
                (*iter).first->doManualRender(mVertexBuffer, mTexture, mCountVertex);
        }
         else
        {
            _target->doRender(mVertexBuffer, mTexture, mCountVertex);
        }
    }
}

注释是俄语的,谷歌翻译成汉语,可能会有错误,还请指出。最后的渲染即调用OpenGLRenderManager::doRender方法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void OpenGLRenderManager::doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count)
{
    OpenGLVertexBuffer* buffer =  static_cast(_buffer);
     unsigned  int buffer_id = buffer->getBufferID();
    MYGUI_PLATFORM_ASSERT(buffer_id,  "Vertex buffer is not created");

     unsigned  int texture_id =  0;
     if (_texture)
    {
        OpenGLTexture* texture =  static_cast(_texture);
        texture_id = texture->getTextureID();
         //MYGUI_PLATFORM_ASSERT(texture_id, "Texture is not created");
    }

    glBindTexture(GL_TEXTURE_2D, texture_id);

    glBindBuffer(GL_ARRAY_BUFFER, buffer_id);

     // enable vertex arrays
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

     // before draw, specify vertex and index arrays with their offsets
    size_t offset =  0;
    glVertexPointer( 3, GL_FLOAT,  sizeof(Vertex), ( void*)offset);
    offset += ( sizeof( float) *  3);
    glColorPointer( 4, GL_UNSIGNED_BYTE,  sizeof(Vertex), ( void*)offset);
    offset += ( 4);
    glTexCoordPointer( 2, GL_FLOAT,  sizeof(Vertex), ( void*)offset);

    glDrawArrays(GL_TRIANGLES,  0, _count);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

    glBindBuffer(GL_ARRAY_BUFFER,  0);
    glBindTexture(GL_TEXTURE_2D,  0);
}

更多资料:
1.纯手绘的MyGUI类图、渲染流程图  http://blog.csdn.net/liigo/article/details/7078533
2.LayerManager   http://blog.csdn.net/geometry_/article/details/7324348
3.mygui跟踪  http://www.cppblog.com/flipcode/archive/2011/06/24/149388.aspx

 

你可能感兴趣的:(3.2,MyGui)