您的位置:首页 > 产品设计 > UI/UE

MyGui笔记(4)渲染过程

2013-10-18 00:30 344 查看
前篇:《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<OpenGLVertexBuffer*>(_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<OpenGLTexture*>(_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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: