Added PostLoad methods to ensure all models have created vertex buffers and all materials have generated shaders before the user gains control of the camera, to fix hitching issues

This commit is contained in:
parax0 2016-02-10 17:38:32 -07:00
parent 6d55444cc2
commit 739e3c51bf
17 changed files with 91 additions and 13 deletions

View File

@ -78,7 +78,9 @@ CMaterial* CMaterial::Clone()
return pOut; return pOut;
} }
void CMaterial::GenerateShader() void CMaterial::GenerateShader(bool AllowRegen /*= true*/)
{
if (mShaderStatus != eShaderExists || AllowRegen)
{ {
delete mpShader; delete mpShader;
mpShader = CShaderGenerator::GenerateShader(*this); mpShader = CShaderGenerator::GenerateShader(*this);
@ -86,6 +88,7 @@ void CMaterial::GenerateShader()
if (!mpShader->IsValidProgram()) mShaderStatus = eShaderFailed; if (!mpShader->IsValidProgram()) mShaderStatus = eShaderFailed;
else mShaderStatus = eShaderExists; else mShaderStatus = eShaderExists;
} }
}
bool CMaterial::SetCurrent(FRenderOptions Options) bool CMaterial::SetCurrent(FRenderOptions Options)
{ {

View File

@ -76,7 +76,7 @@ public:
CMaterial(EGame version, FVertexDescription vtxDesc); CMaterial(EGame version, FVertexDescription vtxDesc);
~CMaterial(); ~CMaterial();
CMaterial* Clone(); CMaterial* Clone();
void GenerateShader(); void GenerateShader(bool AllowRegen = true);
bool SetCurrent(FRenderOptions Options); bool SetCurrent(FRenderOptions Options);
u64 HashParameters(); u64 HashParameters();
void Update(); void Update();

View File

@ -75,6 +75,20 @@ void CModel::BufferGL()
mBuffered = true; mBuffered = true;
} }
void CModel::GenerateMaterialShaders()
{
for (u32 iSet = 0; iSet < mMaterialSets.size(); iSet++)
{
CMaterialSet *pSet = mMaterialSets[iSet];
for (u32 iMat = 0; iMat < pSet->NumMaterials(); iMat++)
{
CMaterial *pMat = pSet->MaterialByIndex(iMat);
pMat->GenerateShader(false);
}
}
}
void CModel::ClearGLBuffer() void CModel::ClearGLBuffer()
{ {
mVBO.Clear(); mVBO.Clear();

View File

@ -23,6 +23,7 @@ public:
~CModel(); ~CModel();
void BufferGL(); void BufferGL();
void GenerateMaterialShaders();
void ClearGLBuffer(); void ClearGLBuffer();
void Draw(FRenderOptions Options, u32 MatSet); void Draw(FRenderOptions Options, u32 MatSet);
void DrawSurface(FRenderOptions Options, u32 Surface, u32 MatSet); void DrawSurface(FRenderOptions Options, u32 Surface, u32 MatSet);

View File

@ -89,6 +89,12 @@ void CStaticModel::BufferGL()
mBuffered = true; mBuffered = true;
} }
void CStaticModel::GenerateMaterialShaders()
{
if (mpMaterial)
mpMaterial->GenerateShader(false);
}
void CStaticModel::ClearGLBuffer() void CStaticModel::ClearGLBuffer()
{ {
mVBO.Clear(); mVBO.Clear();

View File

@ -22,6 +22,7 @@ public:
void AddSurface(SSurface *pSurface); void AddSurface(SSurface *pSurface);
void BufferGL(); void BufferGL();
void GenerateMaterialShaders();
void ClearGLBuffer(); void ClearGLBuffer();
void Draw(FRenderOptions Options); void Draw(FRenderOptions Options);
void DrawSurface(FRenderOptions Options, u32 Surface); void DrawSurface(FRenderOptions Options, u32 Surface);

View File

@ -19,6 +19,15 @@ ENodeType CModelNode::NodeType()
return eModelNode; return eModelNode;
} }
void CModelNode::PostLoad()
{
if (mpModel)
{
mpModel->BufferGL();
mpModel->GenerateMaterialShaders();
}
}
void CModelNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) void CModelNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{ {
if (!mpModel) return; if (!mpModel) return;

View File

@ -18,6 +18,7 @@ public:
explicit CModelNode(CScene *pScene, CSceneNode *pParent = 0, CModel *pModel = 0); explicit CModelNode(CScene *pScene, CSceneNode *pParent = 0, CModel *pModel = 0);
virtual ENodeType NodeType(); virtual ENodeType NodeType();
virtual void PostLoad();
virtual void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo); virtual void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
virtual void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo); virtual void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo);
virtual void DrawSelection(); virtual void DrawSelection();

View File

@ -1,4 +1,5 @@
#include "CScene.h" #include "CScene.h"
#include "CSceneIterator.h"
#include "Core/Render/CGraphics.h" #include "Core/Render/CGraphics.h"
#include "Core/Resource/CResCache.h" #include "Core/Resource/CResCache.h"
#include "Core/Resource/CPoiToWorld.h" #include "Core/Resource/CPoiToWorld.h"
@ -14,6 +15,7 @@
CScene::CScene() CScene::CScene()
: mSplitTerrain(true) : mSplitTerrain(true)
, mRanPostLoad(false)
, mNumNodes(0) , mNumNodes(0)
, mpSceneRootNode(new CRootNode(this, nullptr)) , mpSceneRootNode(new CRootNode(this, nullptr))
, mpArea(nullptr) , mpArea(nullptr)
@ -177,6 +179,7 @@ void CScene::SetActiveArea(CGameArea *pArea)
} }
} }
mRanPostLoad = false;
Log::Write( TString::FromInt32(CSceneNode::NumNodes()) + " nodes" ); Log::Write( TString::FromInt32(CSceneNode::NumNodes()) + " nodes" );
} }
@ -185,6 +188,12 @@ void CScene::SetActiveWorld(CWorld* pWorld)
mpWorld = pWorld; mpWorld = pWorld;
} }
void CScene::PostLoad()
{
mpSceneRootNode->OnLoadFinished();
mRanPostLoad = true;
}
void CScene::ClearScene() void CScene::ClearScene()
{ {
if (mpAreaRootNode) if (mpAreaRootNode)
@ -202,6 +211,10 @@ void CScene::ClearScene()
void CScene::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) void CScene::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{ {
// Call PostLoad the first time the scene is rendered to ensure the OpenGL context has been created before it runs.
if (!mRanPostLoad)
PostLoad();
// Override show flags in game mode // Override show flags in game mode
FShowFlags ShowFlags = (ViewInfo.GameMode ? gkGameModeShowFlags : ViewInfo.ShowFlags); FShowFlags ShowFlags = (ViewInfo.GameMode ? gkGameModeShowFlags : ViewInfo.ShowFlags);
FNodeFlags NodeFlags = NodeFlagsForShowFlags(ShowFlags); FNodeFlags NodeFlags = NodeFlagsForShowFlags(ShowFlags);

View File

@ -25,6 +25,7 @@ class CScene
friend class CSceneIterator; friend class CSceneIterator;
bool mSplitTerrain; bool mSplitTerrain;
bool mRanPostLoad;
u32 mNumNodes; u32 mNumNodes;
CRootNode *mpSceneRootNode; CRootNode *mpSceneRootNode;
@ -52,6 +53,7 @@ public:
CLightNode* CreateLightNode(CLight *pLight); CLightNode* CreateLightNode(CLight *pLight);
void SetActiveArea(CGameArea *pArea); void SetActiveArea(CGameArea *pArea);
void SetActiveWorld(CWorld *pWorld); void SetActiveWorld(CWorld *pWorld);
void PostLoad();
void ClearScene(); void ClearScene();
void AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo); void AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo);
SRayIntersection SceneRayCast(const CRay& rkRay, const SViewInfo& rkViewInfo); SRayIntersection SceneRayCast(const CRay& rkRay, const SViewInfo& rkViewInfo);

View File

@ -36,6 +36,11 @@ public:
return mpCurNode; return mpCurNode;
} }
inline operator bool() const
{
return DoneIterating();
}
inline CSceneNode* operator*() const inline CSceneNode* operator*() const
{ {
return mpCurNode; return mpCurNode;

View File

@ -80,6 +80,14 @@ CColor CSceneNode::WireframeColor() const
} }
// ************ MAIN FUNCTIONALITY ************ // ************ MAIN FUNCTIONALITY ************
void CSceneNode::OnLoadFinished()
{
PostLoad();
for (auto it = mChildren.begin(); it != mChildren.end(); it++)
(*it)->OnLoadFinished();
}
void CSceneNode::Unparent() void CSceneNode::Unparent()
{ {
// May eventually want to reset XForm so global position = local position // May eventually want to reset XForm so global position = local position

View File

@ -67,6 +67,7 @@ public:
virtual CColor TintColor(const SViewInfo& ViewInfo) const; virtual CColor TintColor(const SViewInfo& ViewInfo) const;
virtual CColor WireframeColor() const; virtual CColor WireframeColor() const;
void OnLoadFinished();
void Unparent(); void Unparent();
void RemoveChild(CSceneNode *pChild); void RemoveChild(CSceneNode *pChild);
void DeleteChildren(); void DeleteChildren();
@ -121,14 +122,8 @@ public:
void SetVisible(bool Visible); void SetVisible(bool Visible);
// Static // Static
static int NumNodes(); inline static int NumNodes() { return smNumNodes; }
static CColor skSelectionTint; static CColor skSelectionTint;
}; };
// ************ INLINE FUNCTIONS ************
inline int CSceneNode::NumNodes()
{
return smNumNodes;
}
#endif // CSCENENODE_H #endif // CSCENENODE_H

View File

@ -74,6 +74,15 @@ ENodeType CScriptNode::NodeType()
return eScriptNode; return eScriptNode;
} }
void CScriptNode::PostLoad()
{
if (mpActiveModel)
{
mpActiveModel->BufferGL();
mpActiveModel->GenerateMaterialShaders();
}
}
void CScriptNode::OnTransformed() void CScriptNode::OnTransformed()
{ {
if (mpInstance) if (mpInstance)

View File

@ -27,6 +27,7 @@ class CScriptNode : public CSceneNode
public: public:
CScriptNode(CScene *pScene, CSceneNode *pParent = 0, CScriptObject *pObject = 0); CScriptNode(CScene *pScene, CSceneNode *pParent = 0, CScriptObject *pObject = 0);
ENodeType NodeType(); ENodeType NodeType();
void PostLoad();
void OnTransformed(); void OnTransformed();
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo); void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo); void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo);

View File

@ -19,6 +19,15 @@ ENodeType CStaticNode::NodeType()
return eStaticNode; return eStaticNode;
} }
void CStaticNode::PostLoad()
{
if (mpModel)
{
mpModel->BufferGL();
mpModel->GenerateMaterialShaders();
}
}
void CStaticNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) void CStaticNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{ {
if (!mpModel) return; if (!mpModel) return;

View File

@ -11,6 +11,7 @@ class CStaticNode : public CSceneNode
public: public:
CStaticNode(CScene *pScene, CSceneNode *pParent = 0, CStaticModel *pModel = 0); CStaticNode(CScene *pScene, CSceneNode *pParent = 0, CStaticModel *pModel = 0);
ENodeType NodeType(); ENodeType NodeType();
void PostLoad();
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo); void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo); void Draw(FRenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo);
void DrawSelection(); void DrawSelection();