#include "RenderState.h" #include "Geometry.h" #include "Material.h" #include "ShaderProgram.h" #include "Texture.h" #include "ShaderManager.h" using namespace std; namespace CHCDemoEngine { ///////////////// RenderState::RenderState(): mRenderTechnique(0), mUseAlphaToCoverage(true), mLockCullFaceEnabled(false), mCurrentVboId(-1), mCurrentTexId(0), mCullFaceEnabled(true), mAlphaTestEnabled(false), mTexturesEnabled(false), mCurrentVertexProgram(NULL), mCurrentFragmentProgram(NULL), mLightingEnabled(true), mColorWriteEnabled(true), mDepthWriteEnabled(true), mCurrentTechnique(NULL) { SetMode(RENDER); glEnable(GL_CULL_FACE); glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_LIGHTING); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); } void RenderState::Reset() { SetMode(RENDER); mCurrentVboId = -1; mCurrentTexId = 0; mCullFaceEnabled = true; mAlphaTestEnabled = false; mTexturesEnabled = false; mCurrentVertexProgram = NULL; mCurrentFragmentProgram = NULL; glEnable(GL_CULL_FACE); glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); ShaderManager::GetSingleton()->DisableFragmentProfile(); ShaderManager::GetSingleton()->DisableVertexProfile(); mFragmentProgramEnabled = false; mVertexProgramEnabled = false; mLightingEnabled = true; glEnable(GL_LIGHTING); mColorWriteEnabled = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); mDepthWriteEnabled = true; glDepthMask(GL_TRUE); mCurrentTechnique = NULL; } /** A special technique for occlusion queries. This material has color write, depth write, and lighting turned off */ static Technique GetQueryTechnique() { Technique tech; tech.Init(); tech.SetColorWriteEnabled(false); tech.SetLightingEnabled(false); tech.SetDepthWriteEnabled(false); return tech; } bool RenderState::SetMode(Mode mode) { /////////// //-- just change the mode when necessary if (mode == mMode) return false; mMode = mode; if (mode == QUERY) { /// the query box material static Technique queryTech = GetQueryTechnique(); SetState(&queryTech); glDisableClientState(GL_NORMAL_ARRAY); } else { glEnableClientState(GL_NORMAL_ARRAY); } return true; } void RenderState::SetState(Technique *tech, SceneEntity *ent) { //if (mCurrentTechnique == tech) return; mCurrentTechnique = tech; Texture * const tex = tech->GetTexture(); const bool texturing = (tex != NULL); const bool alphaTest = tech->IsAlphaTestEnabled(); const bool cullFace = tech->IsCullFaceEnabled(); const bool lighting = tech->IsLightingEnabled(); const bool colorWrite = tech->IsColorWriteEnabled(); const bool depthWrite = tech->IsDepthWriteEnabled(); if (mDepthWriteEnabled && !depthWrite) { mDepthWriteEnabled = false; glDepthMask(GL_FALSE); } else if (!mDepthWriteEnabled && depthWrite) { mDepthWriteEnabled = true; glDepthMask(GL_TRUE); } if (mLightingEnabled && !lighting) { mLightingEnabled = false; glDisable(GL_LIGHTING); } else if (!mLightingEnabled && lighting) { mLightingEnabled = true; glEnable(GL_LIGHTING); } if (mColorWriteEnabled && !colorWrite) { mColorWriteEnabled = false; glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } else if (!mColorWriteEnabled && colorWrite) { mColorWriteEnabled = true; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } if (!mLockCullFaceEnabled) { if (mCullFaceEnabled && !cullFace) { mCullFaceEnabled = false; glDisable(GL_CULL_FACE); } else if (!mCullFaceEnabled && cullFace) { mCullFaceEnabled = true; glEnable(GL_CULL_FACE); } } if (mAlphaTestEnabled && !alphaTest) { mAlphaTestEnabled = false; if (mUseAlphaToCoverage) glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); else glDisable(GL_ALPHA_TEST); } else if (!mAlphaTestEnabled && alphaTest) { mAlphaTestEnabled = true; if (mUseAlphaToCoverage) glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); else glEnable(GL_ALPHA_TEST); } if (mTexturesEnabled && !texturing) { mTexturesEnabled = false; glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } else if (!mTexturesEnabled && texturing) { mTexturesEnabled = true; glEnable(GL_TEXTURE_2D); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } // set texture for fixed function rendering if (tex) { if (mCurrentTexId != tex->GetId()) { tex->Bind(); mCurrentTexId = tex->GetId(); } } else { mCurrentTexId = -1; glBindTexture(GL_TEXTURE_2D, 0); } ////////////////// //-- fragment and vertex programs ShaderProgram *frag = tech->GetFragmentProgram(); if (frag) { if (!mFragmentProgramEnabled) { mFragmentProgramEnabled = true; ShaderManager::GetSingleton()->EnableFragmentProfile(); } if (frag != mCurrentFragmentProgram) { mCurrentFragmentProgram = frag; mCurrentFragmentProgram->Bind(); } tech->GetFragmentProgramParameters()->UpdateParameters(ent); } else { if (mFragmentProgramEnabled) { mFragmentProgramEnabled = false; ShaderManager::GetSingleton()->DisableFragmentProfile(); } } ShaderProgram *vtx = tech->GetVertexProgram(); if (vtx) { if (!mVertexProgramEnabled) { mVertexProgramEnabled = true; ShaderManager::GetSingleton()->EnableVertexProfile(); } if (vtx != mCurrentVertexProgram) { mCurrentVertexProgram = vtx; mCurrentVertexProgram->Bind(); } tech->GetVertexProgramParameters()->UpdateParameters(ent); } else { if (mVertexProgramEnabled) { mVertexProgramEnabled = false; ShaderManager::GetSingleton()->DisableVertexProfile(); } } } void RenderState::SetUseAlphaToCoverage(bool useAlphaToCoverage) { mUseAlphaToCoverage = useAlphaToCoverage; } void RenderState::SetRenderTechnique(int t) { mRenderTechnique = t; } int RenderState::GetRenderTechnique() const { return mRenderTechnique; } void RenderState::LockCullFaceEnabled(bool lockCull) { mLockCullFaceEnabled = lockCull; } }