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

View File

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

View File

@ -75,6 +75,20 @@ void CModel::BufferGL()
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()
{
mVBO.Clear();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,5 @@
#include "CScene.h"
#include "CSceneIterator.h"
#include "Core/Render/CGraphics.h"
#include "Core/Resource/CResCache.h"
#include "Core/Resource/CPoiToWorld.h"
@ -14,6 +15,7 @@
CScene::CScene()
: mSplitTerrain(true)
, mRanPostLoad(false)
, mNumNodes(0)
, mpSceneRootNode(new CRootNode(this, nullptr))
, mpArea(nullptr)
@ -177,6 +179,7 @@ void CScene::SetActiveArea(CGameArea *pArea)
}
}
mRanPostLoad = false;
Log::Write( TString::FromInt32(CSceneNode::NumNodes()) + " nodes" );
}
@ -185,6 +188,12 @@ void CScene::SetActiveWorld(CWorld* pWorld)
mpWorld = pWorld;
}
void CScene::PostLoad()
{
mpSceneRootNode->OnLoadFinished();
mRanPostLoad = true;
}
void CScene::ClearScene()
{
if (mpAreaRootNode)
@ -202,6 +211,10 @@ void CScene::ClearScene()
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
FShowFlags ShowFlags = (ViewInfo.GameMode ? gkGameModeShowFlags : ViewInfo.ShowFlags);
FNodeFlags NodeFlags = NodeFlagsForShowFlags(ShowFlags);

View File

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

View File

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

View File

@ -80,6 +80,14 @@ CColor CSceneNode::WireframeColor() const
}
// ************ MAIN FUNCTIONALITY ************
void CSceneNode::OnLoadFinished()
{
PostLoad();
for (auto it = mChildren.begin(); it != mChildren.end(); it++)
(*it)->OnLoadFinished();
}
void CSceneNode::Unparent()
{
// 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 WireframeColor() const;
void OnLoadFinished();
void Unparent();
void RemoveChild(CSceneNode *pChild);
void DeleteChildren();
@ -121,14 +122,8 @@ public:
void SetVisible(bool Visible);
// Static
static int NumNodes();
inline static int NumNodes() { return smNumNodes; }
static CColor skSelectionTint;
};
// ************ INLINE FUNCTIONS ************
inline int CSceneNode::NumNodes()
{
return smNumNodes;
}
#endif // CSCENENODE_H

View File

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

View File

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

View File

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

View File

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