#include "RenderState.h" #include "Geometry.h" #include "Material.h" #include "ShaderProgram.h" #include "Texture.h" #include "ResourceManager.h" using namespace std; namespace CHCDemoEngine { ///////////////// RenderState::RenderState(): mRenderType(FORWARD), mUseAlphaToCoverage(true), mLockCullFaceEnabled(false) { 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); } 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); ResourceManager::GetSingleton()->DisableFragmentProfile(); ResourceManager::GetSingleton()->DisableVertexProfile(); mFragmentProgramEnabled = false; mVertexProgramEnabled = false; } // q matt: is this function really necessary or would it be better // to just create a query material and use the setstate function? bool RenderState::SetMode(Mode mode) { /////////// //-- just change the modewhen necessary if (mode == mMode) return false; mMode = mode; if (mode == QUERY) { if (mRenderType != DEPTH_PASS) { glDisable(GL_LIGHTING); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } if (mFragmentProgramEnabled) { ResourceManager::GetSingleton()->DisableFragmentProfile(); } if (mVertexProgramEnabled) { ResourceManager::GetSingleton()->DisableVertexProfile(); } glDepthMask(GL_FALSE); static Technique defaultTech; SetState(&defaultTech); } else // mode returns to render { ///////////// //-- restore render state if (mRenderType != DEPTH_PASS) { glEnable(GL_LIGHTING); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } if (mFragmentProgramEnabled) { ResourceManager::GetSingleton()->EnableFragmentProfile(); } if (mVertexProgramEnabled) { ResourceManager::GetSingleton()->EnableVertexProfile(); } glDepthMask(GL_TRUE); } return true; } void RenderState::SetState(Technique *tech) { Texture *tex = tech->GetTexture(); const bool texturing = (tex != NULL); bool alphaTest = tech->IsAlphaTestEnabled(); bool cullFace = tech->IsCullFaceEnabled(); 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 || (mRenderType == DEPTH_PASS) && !mAlphaTestEnabled)) { mTexturesEnabled = false; if (!tech->GetFragmentProgram()) glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } else if (!mTexturesEnabled && texturing) { // support only alpha textures in depth pass if ((mRenderType != DEPTH_PASS) || mAlphaTestEnabled) { mTexturesEnabled = true; if (!tech->GetFragmentProgram()) glEnable(GL_TEXTURE_2D); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } } ////////// //-- fragment and vertex programs ShaderProgram *frag = tech->GetFragmentProgram(); if (frag) { if (!mFragmentProgramEnabled) { mFragmentProgramEnabled = true; ResourceManager::GetSingleton()->EnableFragmentProfile(); } if (frag != mCurrentFragmentProgram) { mCurrentFragmentProgram = frag; mCurrentFragmentProgram->Bind(); } tech->GetFragmentProgramParameters()->UpdateParameters(); } else { if (mFragmentProgramEnabled) { mFragmentProgramEnabled = false; ResourceManager::GetSingleton()->DisableFragmentProfile(); } } ShaderProgram *vert = tech->GetVertexProgram(); if (vert) { if (!mVertexProgramEnabled) { mVertexProgramEnabled = true; ResourceManager::GetSingleton()->EnableVertexProfile(); } if (vert != mCurrentVertexProgram) { mCurrentVertexProgram = vert; mCurrentVertexProgram->Bind(); } tech->GetVertexProgramParameters()->UpdateParameters(); } else { if (mVertexProgramEnabled) { mVertexProgramEnabled = false; ResourceManager::GetSingleton()->DisableVertexProfile(); } } if (!mFragmentProgramEnabled) { // set FORWARD texture if (tex) { if (mCurrentTexId != tex->GetId()) { tex->Bind(); mCurrentTexId = tex->GetId(); } } else { mCurrentTexId = 0; glBindTexture(GL_TEXTURE_2D, 0); } } } void RenderState::SetUseAlphaToCoverage(bool useAlphaToCoverage) { mUseAlphaToCoverage = useAlphaToCoverage; } void RenderState::SetRenderPassType(RenderPassType t) { mRenderType = t; } RenderState::RenderPassType RenderState::GetRenderPassType() const { return mRenderType; } void RenderState::LockCullFaceEnabled(bool lockCull) { mLockCullFaceEnabled = lockCull; } }