#include "OgreDepthShadowRecieverRenderTechnique.h" #include "OgreTechniqueGroup.h" #include "OgreIlluminationManager.h" #include "OgreDepthShadowMapRenderingRun.h" OgreDepthShadowRecieverRenderTechnique::OgreDepthShadowRecieverRenderTechnique( int maxlights, String shadowVertexProgram, String shadowFragmentProgram, bool setLightViewMatrix, bool setLightViewProjMatrix, bool setLightProjFarPlane, String lightViewProjParamName, String lightViewParamName, String lightFarPlaneParamName, Pass* pass, OgreRenderable* parentRenderable, OgreTechniqueGroup* parentTechniqueGroup) :RenderTechnique( parentRenderable, parentTechniqueGroup), OgreRenderTechnique(pass, parentRenderable, parentTechniqueGroup), DepthShadowRecieverRenderTechnique(parentRenderable, parentTechniqueGroup) { this->maxlights = maxlights; this->shadowVertexProgram = shadowVertexProgram ; this->shadowFragmentProgram = shadowFragmentProgram; this->setLightViewMatrix = setLightViewMatrix; this->setLightViewProjMatrix = setLightViewProjMatrix; this->setLightProjFarPlane = setLightProjFarPlane; this->lightViewProjParamName = lightViewProjParamName; this->lightViewParamName = lightViewParamName; this->lightFarPlaneParamName = lightFarPlaneParamName; //insert new passes Ogre::Technique* techn = pass->getParent(); Technique::PassIterator it = techn->getPassIterator(); int index = 0; while(it.hasMoreElements()) { if( it.getNext() == pass) break; index++; it.moveNext(); } index++; for(int i = 0; i < maxlights; i++) { int lastpass = techn->getNumPasses(); Pass* newpass = techn->createPass(); passes.push_back(newpass); newpass->setVertexProgram(shadowVertexProgram); newpass->setFragmentProgram(shadowFragmentProgram); GpuProgramParameters* Vparams = newpass->getVertexProgramParameters().getPointer(); Vparams->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); Vparams->setNamedAutoConstant("world", GpuProgramParameters::ACT_WORLD_MATRIX); GpuProgramParameters* Fparams = newpass->getFragmentProgramParameters().getPointer(); TextureUnitState* st = newpass->createTextureUnitState(); st->setTextureFiltering(TFO_ANISOTROPIC); st->setTextureAddressingMode(TextureUnitState::TAM_BORDER); st->setTextureBorderColour(ColourValue::White); newpass->setSceneBlending(SBT_MODULATE); //newpass->setSceneBlending(SBF_ONE, SBF_ZERO); newpass->setDepthBias(1); techn->movePass(lastpass, index); } } OgreDepthShadowRecieverRenderTechnique::~OgreDepthShadowRecieverRenderTechnique() { } void OgreDepthShadowRecieverRenderTechnique::update(unsigned long frameNum) { LightList lights; Root::getSingleton()._getCurrentSceneManager()->_populateLightList( ((OgreSharedRuns*) sharedRuns)->getRootPosition(), 100000.0, lights); //fill passes unsigned int l = 0; for(unsigned int i = 0; i < passes.size(); i++) { while(lights.size() != l && !lights.at(l)->getCastShadows()) l++; if(lights.size() > l) { //create run if not exists OgreIlluminationManager::getSingleton().createPerLightRun(lights.at(l)->getName(), ILLUMRUN_DEPTH_SHADOWMAP); //update light depth map OgreIlluminationManager::getSingleton().updatePerLightRun(lights.at(l)->getName(), ILLUMRUN_DEPTH_SHADOWMAP, frameNum); //set texture to pass OgreDepthShadowMapRenderingRun* depthRun = (OgreDepthShadowMapRenderingRun*) OgreIlluminationManager::getSingleton() .getPerLightRun(lights.at(l)->getName(), ILLUMRUN_DEPTH_SHADOWMAP)->asOgreRenderingRun(); passes.at(i)->getTextureUnitState(0)->setTextureName( depthRun->getDepthMapTextureName()); //TODO: set matrices GpuProgramParametersSharedPtr fpParams = passes.at(i)->getFragmentProgramParameters(); GpuProgramParametersSharedPtr vpParams = passes.at(i)->getVertexProgramParameters(); //fpParams->setNamedConstant("lightViewProj", depthRun->getLightViewProjMatrix()); if(setLightViewProjMatrix) vpParams->setNamedConstant(lightViewProjParamName, depthRun->getLightViewProjMatrix()); if(setLightViewMatrix) vpParams->setNamedConstant(lightViewParamName, depthRun->getLightViewMatrix()); if(setLightProjFarPlane) fpParams->setNamedConstant(lightFarPlaneParamName, depthRun->getLightFarPlane()); passes.at(i)->setActive(true); } else passes.at(i)->setActive(false); } } ///Technique parsers namespace DepthShadowRecieverParsers { void parseMaxLights(String& params, RenderTechniqueFactory* factory) { OgreDepthShadowRecieverRenderTechniqueFactory* f = (OgreDepthShadowRecieverRenderTechniqueFactory*) factory; f->maxlights = StringConverter::parseInt(params); } void parseVertexProgram(String& params, RenderTechniqueFactory* factory) { OgreDepthShadowRecieverRenderTechniqueFactory* f = (OgreDepthShadowRecieverRenderTechniqueFactory*) factory; f->shadowVertexProgram = params; } void parseFragmentProgram(String& params, RenderTechniqueFactory* factory) { OgreDepthShadowRecieverRenderTechniqueFactory* f = (OgreDepthShadowRecieverRenderTechniqueFactory*) factory; f->shadowFragmentProgram = params; } void parseSetLightViewProj(String& params, RenderTechniqueFactory* factory) { OgreDepthShadowRecieverRenderTechniqueFactory* f = (OgreDepthShadowRecieverRenderTechniqueFactory*) factory; StringVector vecparams = StringUtil::split(params, " \t"); f->setLightViewProjMatrix = StringConverter::parseBool(vecparams[0]); if(f->setLightViewProjMatrix && vecparams.size() > 1) f->lightViewProjParamName = vecparams[1]; } void parseSetLightView(String& params, RenderTechniqueFactory* factory) { OgreDepthShadowRecieverRenderTechniqueFactory* f = (OgreDepthShadowRecieverRenderTechniqueFactory*) factory; StringVector vecparams = StringUtil::split(params, " \t"); f->setLightViewMatrix = StringConverter::parseBool(vecparams[0]); if(f->setLightViewMatrix && vecparams.size() > 1) f->lightViewParamName = vecparams[1]; } void parseSetLightFarPlane(String& params, RenderTechniqueFactory* factory) { OgreDepthShadowRecieverRenderTechniqueFactory* f = (OgreDepthShadowRecieverRenderTechniqueFactory*) factory; StringVector vecparams = StringUtil::split(params, " \t"); f->setLightProjFarPlane = StringConverter::parseBool(vecparams[0]); if(f->setLightProjFarPlane && vecparams.size() > 1) f->lightFarPlaneParamName = vecparams[1]; } } OgreDepthShadowRecieverRenderTechniqueFactory::OgreDepthShadowRecieverRenderTechniqueFactory() { typeName = "DepthShadowReciever"; using namespace DepthShadowRecieverParsers; //register parsers this->attributeParsers.insert(AttribParserList::value_type("max_light_count", (ILLUM_ATTRIBUTE_PARSER) parseMaxLights)); this->attributeParsers.insert(AttribParserList::value_type("vertex_program_name", (ILLUM_ATTRIBUTE_PARSER) parseVertexProgram)); this->attributeParsers.insert(AttribParserList::value_type("fragment_program_name", (ILLUM_ATTRIBUTE_PARSER) parseFragmentProgram)); this->attributeParsers.insert(AttribParserList::value_type("set_light_viewproj", (ILLUM_ATTRIBUTE_PARSER) parseSetLightViewProj)); this->attributeParsers.insert(AttribParserList::value_type("set_light_view", (ILLUM_ATTRIBUTE_PARSER) parseSetLightView)); this->attributeParsers.insert(AttribParserList::value_type("set_light_farplane", (ILLUM_ATTRIBUTE_PARSER) parseSetLightFarPlane)); } OgreRenderTechnique* OgreDepthShadowRecieverRenderTechniqueFactory::createInstance( IllumTechniqueParams* params, Pass* pass, OgreRenderable* parentRenderable, OgreTechniqueGroup* parentTechniqueGroup) { //reset parameters maxlights = 1; shadowVertexProgram = "GameTools/ShadowMap/ShadowVS"; shadowFragmentProgram = "GameTools/ShadowMap/ShadowPS"; setLightViewMatrix = false; setLightViewProjMatrix = true; setLightProjFarPlane = false; lightViewProjParamName = "lightViewProj"; lightViewParamName = "lightView"; lightFarPlaneParamName = "lightFarPlane"; parseParams(params); OgreDepthShadowRecieverRenderTechnique* result = new OgreDepthShadowRecieverRenderTechnique( maxlights, shadowVertexProgram, shadowFragmentProgram, setLightViewMatrix , setLightViewProjMatrix, setLightProjFarPlane, lightViewProjParamName, lightViewParamName, lightFarPlaneParamName, pass, parentRenderable, parentTechniqueGroup); return result; }