MyGui笔记(4)渲染过程
来源:互联网 发布:去哪里投诉淘宝卖家 编辑:程序博客网 时间:2024/05/16 08:27
前篇:《MyGui笔记(3)控件对齐方式和所在层》
本篇:记录下渲染的过程。
环境:MyGui3.2.0(OpenGL平台)
MyGui的渲染过程比较复杂,这里仅记录一下一些要点,如有错误的地方,还请指出。在第一篇有提到在BaseManager::run函数里面进行每一帧的绘制,调用的是drawOneFrame()方法,这个方法代码如下:
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);
}
{
// 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);
}
调用的是OpenGLRenderManager的drawOneFrame()方法,代码如下:
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;
}
{
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方法,代码如下:
2
3
4
5
6
void RenderManager::onRenderToTarget(IRenderTarget* _target, bool _update)
{
LayerManager* layers = LayerManager::getInstancePtr();
if (layers != nullptr)
layers->renderToTarget(_target, _update);
}
{
LayerManager* layers = LayerManager::getInstancePtr();
if (layers != nullptr)
layers->renderToTarget(_target, _update);
}
可以看到在这里调用的是LayerManager层管理器来进行绘制,具体代码如下:
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);
}
}
{
for (VectorLayer::iterator iter = mLayerNodes.begin(); iter != mLayerNodes.end(); ++iter)
{
(*iter)->renderToTarget(_target, _update);
}
}
对mLayerNodes里的所有层依次进行调用渲染,故定义在MyGUI_Layers.xml文件最上面的层,将会最先开始渲染,顺序如Wallpaper→Back→Overlapped→……。具体的渲染方法是根据不同的层类型来进行的,代码分别如下:
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;
}
{
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方法,代码如下:
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;
}
{
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,代码如下:
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);
}
}
}
{
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方法,代码如下:
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);
}
{
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
- MyGui笔记(4)渲染过程
- MyGUI 学习笔记(四)——MyGUI sample 4——13.03.11
- 虚幻4 D3D渲染过程的笔记
- MyGUI 学习笔记(一)——MyGUI sample1——13.01.23
- MyGUI 学习笔记(二)——MyGUI sample2——13.01.23
- MyGUI 学习笔记(三)——MyGUI sample3——13.02.07
- MyGUI 学习笔记(五)——MyGUI 中其他文件1——13.03.12
- mygui阅读笔记(2) myGui的Delegate
- 纯手绘的MyGUI类图、渲染流程图
- MyGui笔记(1)建立第一个工程
- MyGui笔记(2)控件类型和皮肤
- MyGui笔记(3)控件对齐方式和所在层
- 帧渲染系统过程笔记
- MyGUI 学习(2)
- MyGUI 学习(1)
- MyGUI的阅读笔记(1) myGUi的单件
- mygui初探(一)基础
- 虚幻4 渲染staticmesh过程。
- 分割字符串的比较完美实现(c++,stl)
- Android 滑动效果高级篇(八)—— 自定义控件
- MyGui笔记(3)控件对齐方式和所在层
- Android如何运行真机在eclipse上调试应用?
- Android 滑动效果高级篇(七)—— 华丽翻页效果
- MyGui笔记(4)渲染过程
- Android 滑动效果进阶篇(六)—— 倒影效果
- Android 滑动效果进阶篇(五)—— 3D旋转
- 批处理读取用户输入值作为参数传给ant脚本执行
- 程序员的职业规划
- Android 滑动效果基础篇(四)—— Gallery + GridView
- 布偶猫综述
- Android 滑动效果基础篇(三)—— Gallery仿图像集浏览
- CSDN第一篇博客,找工作日记第一篇