昨天提到的我想到了个优化渲染的新方法。。今天花了一个早上终于实现了。5555其实不需要这么久,偏偏是一个小小的BUG花了我两个小时。马上进入正题吧。 原来的GUI渲染系统是每个Window都继承于RenderCache,每个RenderCache中保存着需要渲染的矩形信息,然后每帧渲染的时候一个个矩形添加到渲染器中再动态修改顶点坐标(一个矩形对应6个顶点)。慢就慢在动态修改顶点! 今天实现的新方法,就是直接把顶点保存在RenderCache中,然后每帧渲染的时候直接DrawIndexedPrimitiveUP出来,Release版速度从500提升到550FPS了。DEBUG版从130提升到360FPS(主要是stl的东西在debug版下慢许多)。 贴下RenderCache的代码 h文件 #pragma once #include "GameCorePreReq.h" #include "Rect.h" #include "ListHelper.h" #include "GCVector3.h" #include "GCVector2.h" #include "GCArray.h"
#define GUI_Z 0.0f
// 四个角的颜色 struct BoundsColor { BoundsColor( GC3DCOLOR crTopLeft , GC3DCOLOR crTopRight , GC3DCOLOR crBottomLeft , GC3DCOLOR crBottomRight ) : m_crTopLeft(crTopLeft) , m_crTopRight(crTopRight) , m_crBottomLeft(crBottomLeft) , m_crBottomRight(crBottomRight) {
};
BoundsColor(GC3DCOLOR color) : m_crTopLeft(color) , m_crTopRight(color) , m_crBottomLeft(color) , m_crBottomRight(color) {
};
BoundsColor(const BoundsColor &color) { *this = color; };
BoundsColor(){};
void SetRefAlpha(const float &fAlpha) { GC3DCOLOR_SETA(m_crTopLeft , GC3DCOLOR_GETA(m_crTopLeft) * fAlpha); GC3DCOLOR_SETA(m_crTopRight , GC3DCOLOR_GETA(m_crTopRight) * fAlpha); GC3DCOLOR_SETA(m_crBottomLeft , GC3DCOLOR_GETA(m_crBottomLeft) * fAlpha); GC3DCOLOR_SETA(m_crBottomRight , GC3DCOLOR_GETA(m_crBottomRight) * fAlpha); }
void SetAlpha(const float &fAlpha) { GC3DCOLOR_SETA(m_crTopLeft , fAlpha); GC3DCOLOR_SETA(m_crTopRight , fAlpha); GC3DCOLOR_SETA(m_crBottomLeft , fAlpha); GC3DCOLOR_SETA(m_crBottomRight , fAlpha); } GC3DCOLOR m_crTopLeft; GC3DCOLOR m_crTopRight; GC3DCOLOR m_crBottomLeft; GC3DCOLOR m_crBottomRight;
BoundsColor & operator =(const BoundsColor& color) { m_crTopLeft = color.m_crTopLeft; m_crTopRight = color.m_crTopRight; m_crBottomLeft = color.m_crBottomLeft; m_crBottomRight = color.m_crBottomRight; return *this; } };
// 一个顶点 struct QuadVertex { QuadVertex(f32 x , f32 y , GC3DCOLOR color , f32 ux , f32 uy , Texture *pTexture) : m_pos(x , y , GUI_Z) , m_rhw(1) , m_diffuse(color) , m_uv(ux , uy) , m_pTexture(pTexture) {
}; Vector3 m_pos; // 顶点的位置 float m_rhw; // 始终设置为1 GC3DCOLOR m_diffuse; // 颜色 Vector2 m_uv; // 贴图坐标 Texture* m_pTexture; // 纹理 };
// 需要渲染的队列的一个方块 struct GUIRenderQuad { GUIRenderQuad(const Rect& rectDest, const BoundsColor& boundsColor, Texture* pTexture, const RectFloat &rectTexture) : m_topLeft(rectDest.left , rectDest.top , boundsColor.m_crTopLeft , rectTexture.left , rectTexture.top , pTexture) , m_topRight(rectDest.right , rectDest.top , boundsColor.m_crTopRight , rectTexture.right , rectTexture.top , pTexture) , m_bottomLeft(rectDest.left , rectDest.bottom , boundsColor.m_crBottomLeft , rectTexture.left , rectTexture.bottom , pTexture) , m_bottomRight(rectDest.right , rectDest.bottom , boundsColor.m_crBottomRight , rectTexture.right , rectTexture.bottom , pTexture) {
}; QuadVertex m_topLeft; QuadVertex m_topRight; QuadVertex m_bottomLeft; QuadVertex m_bottomRight; };
typedef Array<GUIRenderQuad> ListGUIRenderQuad;
class GAMECORE_EXPORT GUIRenderCache { protected: // 不允许显式创建,只可以继承 GUIRenderCache(void); public: virtual ~GUIRenderCache(void);
// 添加到渲染队列,支持很多版本的重载 void AddCache(const Rect& rectDest, const BoundsColor& boundsColor, Texture* pTexture, const RectFloat &rectTexture) { AddCache(GUIRenderQuad(rectDest , boundsColor , pTexture , rectTexture)); }; void AddCache(const Rect& rectDest, const BoundsColor& boundsColor, Texture* pTexture) { AddCache(GUIRenderQuad(rectDest , boundsColor , pTexture , RectFloat(0,0,1,1))); }; void AddCache(const Rect& rectDest, const BoundsColor& boundsColor) { AddCache(GUIRenderQuad(rectDest , boundsColor , 0 , RectFloat(0,0,1,1))); }; void AddCache(const GUIRenderQuad *quadPtr) { AddCache(*quadPtr); } void AddCache(const GUIRenderQuad& quad) { m_listGUIRenderQuad.push_back(quad); } // 渲染到队列 void RenderCache(); // 直接渲染 void RenderDirect(); // 清空cache队列 void ClearCacheList(void) { m_listGUIRenderQuad.clear(); }
void SetDirty(bool bDirty){m_bDirty = bDirty;}; const bool IsDirty() const{return m_bDirty;}; protected:
void Cache() { // 从新Cache队列 if(m_bDirty) { ClearCacheList(); DoCache(); m_bDirty = false; } } // Cache需要渲染的项目 virtual void DoCache(){};
ListGUIRenderQuad m_listGUIRenderQuad; // 渲染队列 bool m_bDirty; // 需要重新Cache需要渲染的项目 };
cpp文件 #include "GameCorePreReq.h" #include "GUIRenderCache.h" #include "Systems.h" #include "GUIRendererSystem.h"
GUIRenderCache::GUIRenderCache(void) : m_bDirty(true) { }
GUIRenderCache::~GUIRenderCache(void) { }
// 渲染需要Cache队列 void GUIRenderCache::RenderCache() { Cache(); if(m_listGUIRenderQuad.empty()) return; ListGUIRenderQuad *pQuad = &m_listGUIRenderQuad; Systems::GetSingleton().GetGUIRendererSystem()->PushBack(pQuad); }
void GUIRenderCache::RenderDirect() { Cache(); if(m_listGUIRenderQuad.empty()) return; Systems::GetSingleton().GetGUIRendererSystem()->RenderDirect(&m_listGUIRenderQuad); }
|