#include "OgreCausticReceiverRenderTechnique.h" #include "OgreTechniqueGroup.h" #include "OgreIlluminationManager.h" #include "OgreCausticCubeMapRenderingRun.h" #include "OgreCubeMapRenderingRun.h" OgreCausticReceiverRenderTechnique::OgreCausticReceiverRenderTechnique( int maxcasters, String causticVertexProgram, String causticFragmentProgram, SceneBlendFactor passBlendingSRC, SceneBlendFactor passBlendingDEST, bool createNewPasses, int startTextureUnitID, String casterCenterVariableName, String attenuationVariableName, bool bindDistanceMap, Pass* pass, OgreRenderable* parentRenderable, OgreTechniqueGroup* parentTechniqueGroup) :RenderTechnique( parentRenderable, parentTechniqueGroup), OgreRenderTechnique(pass, parentRenderable, parentTechniqueGroup), CausticReceiverRenderTechnique(parentRenderable, parentTechniqueGroup) { this->passBlendingSRC = passBlendingSRC; this->passBlendingDEST = passBlendingDEST; this->maxcasters = maxcasters; this->causticVertexProgram = causticVertexProgram; this->causticFragmentProgram = causticFragmentProgram; this->createNewPasses = createNewPasses; this->startTextureUnitID = startTextureUnitID; this->casterCenterVariableName = casterCenterVariableName; this->attenuationVariableName = attenuationVariableName; this->bindDistanceMap = bindDistanceMap; bindAttenuation = false; if(attenuationVariableName != "") bindAttenuation = true; if(createNewPasses) { //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 < maxcasters; i++) { int lastpass = techn->getNumPasses(); Pass* newpass = techn->createPass(); passes.push_back(newpass); newpass->setVertexProgram(causticVertexProgram); newpass->setFragmentProgram(causticFragmentProgram); GpuProgramParameters* Vparams = newpass->getVertexProgramParameters().getPointer(); Vparams->setNamedAutoConstant("WorldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); Vparams->setNamedAutoConstant("World", GpuProgramParameters::ACT_WORLD_MATRIX); GpuProgramParameters* Fparams = newpass->getFragmentProgramParameters().getPointer(); //Fparams->setNamedConstant("cubeMapCameraPosition", Vector3(0,0,0)); TextureUnitState* st = newpass->createTextureUnitState(); st->setTextureFiltering(TFO_BILINEAR); if(bindDistanceMap) { TextureUnitState* st2 = newpass->createTextureUnitState(); st2->setTextureFiltering(TFO_BILINEAR); } newpass->setSceneBlending(passBlendingSRC, passBlendingDEST); newpass->setDepthBias(1); techn->movePass(lastpass, index); } } } OgreCausticReceiverRenderTechnique::~OgreCausticReceiverRenderTechnique() { } void OgreCausticReceiverRenderTechnique::update(unsigned long frameNum) { //find nearest casters causticCasters.clear(); OgreIlluminationManager::getSingleton().getNearestCausticCasters( ((OgreSharedRuns*)sharedRuns)->getRootPosition(), &causticCasters, maxcasters); //fill passes for(unsigned int i = 0; i < maxcasters; i++) { if(causticCasters.size() > i) { //update caustic caster causticCasters.at(i)->updateRun(ILLUMRUN_PHOTONMAP, frameNum); causticCasters.at(i)->updateRun(ILLUMRUN_CAUSTIC_CUBEMAP, frameNum); //set texture to pass OgreCausticCubeMapRenderingRun* cauCubeRun = (OgreCausticCubeMapRenderingRun*) causticCasters.at(i)-> getRun(ILLUMRUN_CAUSTIC_CUBEMAP)->asOgreRenderingRun(); Pass* passToSet = this->pass; int p = bindDistanceMap?i*2:i; int textureUnit = startTextureUnitID + p; if(createNewPasses) { passToSet = passes.at(i); passToSet->setActive(true); textureUnit = 0; } passToSet->getTextureUnitState(textureUnit)->setTextureName( cauCubeRun->getCausticCubeMapTextureName()); if(bindDistanceMap) { OgreCubeMapRenderingRun* distCubeRun = (OgreCubeMapRenderingRun*) causticCasters.at(i)-> getRun(ILLUMRUN_DISTANCE_CUBEMAP)->asOgreRenderingRun(); if(distCubeRun) passToSet->getTextureUnitState(textureUnit + 1)->setTextureName( distCubeRun->getCubeMapTextureName()); } //set caster position nad caustic attenuation GpuProgramParameters* Fparams = passToSet->getFragmentProgramParameters().getPointer(); String centerVarName = casterCenterVariableName; String attenuationVarName = attenuationVariableName; if(!createNewPasses) { centerVarName += StringConverter::toString(i+1); attenuationVarName += StringConverter::toString(i+1); } Fparams->setNamedConstant(centerVarName, causticCasters.at(i)->getRootPosition(ILLUMRUN_CAUSTIC_CUBEMAP)); if(bindAttenuation) Fparams->setNamedConstant(attenuationVarName, cauCubeRun->getAttenuation()); } else if(createNewPasses) passes.at(i)->setActive(false); } } namespace CausticReceiverParsers { ///Technique parsers void parseMaxCasters(String& params, RenderTechniqueFactory* factory) { OgreCausticReceiverRenderTechniqueFactory* f = (OgreCausticReceiverRenderTechniqueFactory*) factory; f->maxcasters = StringConverter::parseInt(params); } void parseVertexProgram(String& params, RenderTechniqueFactory* factory) { OgreCausticReceiverRenderTechniqueFactory* f = (OgreCausticReceiverRenderTechniqueFactory*) factory; f->causticVertexProgram = params; } void parseFragmentProgram(String& params, RenderTechniqueFactory* factory) { OgreCausticReceiverRenderTechniqueFactory* f = (OgreCausticReceiverRenderTechniqueFactory*) factory; f->causticFragmentProgram = params; } SceneBlendFactor convertBlendFactor(const String& param) { if (param == "one") return SBF_ONE; else if (param == "zero") return SBF_ZERO; else if (param == "dest_colour") return SBF_DEST_COLOUR; else if (param == "src_colour") return SBF_SOURCE_COLOUR; else if (param == "one_minus_dest_colour") return SBF_ONE_MINUS_DEST_COLOUR; else if (param == "one_minus_src_colour") return SBF_ONE_MINUS_SOURCE_COLOUR; else if (param == "dest_alpha") return SBF_DEST_ALPHA; else if (param == "src_alpha") return SBF_SOURCE_ALPHA; else if (param == "one_minus_dest_alpha") return SBF_ONE_MINUS_DEST_ALPHA; else if (param == "one_minus_src_alpha") return SBF_ONE_MINUS_SOURCE_ALPHA; } void parsePassBlending(String& params, RenderTechniqueFactory* factory) { OgreCausticReceiverRenderTechniqueFactory* f = (OgreCausticReceiverRenderTechniqueFactory*) factory; StringVector vecparams = StringUtil::split(params, " \t"); if(vecparams.size() == 1) { if (vecparams[0] == "none") { f->passBlendingSRC = SBF_ONE; f->passBlendingDEST = SBF_ZERO; } if (vecparams[0] == "add") { f->passBlendingSRC = SBF_ONE; f->passBlendingDEST = SBF_ONE; } else if (vecparams[0] == "modulate") { f->passBlendingSRC = SBF_DEST_COLOUR; f->passBlendingDEST = SBF_ZERO; } else if (vecparams[0] == "colour_blend") { f->passBlendingSRC = SBF_SOURCE_COLOUR; f->passBlendingDEST = SBF_ONE_MINUS_SOURCE_COLOUR; } else if (vecparams[0] == "alpha_blend") { f->passBlendingSRC = SBF_SOURCE_ALPHA; f->passBlendingDEST = SBF_ONE_MINUS_SOURCE_ALPHA; } } else if (vecparams.size() == 2) { f->passBlendingSRC = convertBlendFactor(vecparams[0]); f->passBlendingDEST = convertBlendFactor(vecparams[1]) ; } } void parseCreateNewPasses(String& params, RenderTechniqueFactory* factory) { OgreCausticReceiverRenderTechniqueFactory* f = (OgreCausticReceiverRenderTechniqueFactory*) factory; f->createNewPasses = StringConverter::parseBool(params); } void parseStartTexID(String& params, RenderTechniqueFactory* factory) { OgreCausticReceiverRenderTechniqueFactory* f = (OgreCausticReceiverRenderTechniqueFactory*) factory; f->startTextureUnitID = StringConverter::parseInt(params); } void parseCenterVarName(String& params, RenderTechniqueFactory* factory) { OgreCausticReceiverRenderTechniqueFactory* f = (OgreCausticReceiverRenderTechniqueFactory*) factory; f->casterCenterVariableName = params; } void parseAttenuationVarName(String& params, RenderTechniqueFactory* factory) { OgreCausticReceiverRenderTechniqueFactory* f = (OgreCausticReceiverRenderTechniqueFactory*) factory; f->attenuationVariableName = params; } void parseBindDistanceMap(String& params, RenderTechniqueFactory* factory) { OgreCausticReceiverRenderTechniqueFactory* f = (OgreCausticReceiverRenderTechniqueFactory*) factory; f->bindDistanceMap = StringConverter::parseBool(params); } } OgreCausticReceiverRenderTechniqueFactory::OgreCausticReceiverRenderTechniqueFactory() { typeName = "CausticReceiver"; using namespace CausticReceiverParsers; //register parsers this->attributeParsers.insert(AttribParserList::value_type("max_caster_count", (ILLUM_ATTRIBUTE_PARSER) parseMaxCasters)); 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("pass_blending", (ILLUM_ATTRIBUTE_PARSER) parsePassBlending)); this->attributeParsers.insert(AttribParserList::value_type("new_passes", (ILLUM_ATTRIBUTE_PARSER) parseCreateNewPasses)); this->attributeParsers.insert(AttribParserList::value_type("start_tex_id", (ILLUM_ATTRIBUTE_PARSER) parseStartTexID)); this->attributeParsers.insert(AttribParserList::value_type("center_var_name", (ILLUM_ATTRIBUTE_PARSER) parseCenterVarName)); this->attributeParsers.insert(AttribParserList::value_type("attenuation_var_name", (ILLUM_ATTRIBUTE_PARSER) parseAttenuationVarName)); this->attributeParsers.insert(AttribParserList::value_type("bind_distance_map", (ILLUM_ATTRIBUTE_PARSER) parseBindDistanceMap)); } OgreRenderTechnique* OgreCausticReceiverRenderTechniqueFactory::createInstance( IllumTechniqueParams* params, Pass* pass, OgreRenderable* parentRenderable, OgreTechniqueGroup* parentTechniqueGroup) { //reset parameters maxcasters = 1; causticVertexProgram = "GTP/Basic/Shaded_VS"; causticFragmentProgram = "GTP/Caustic/GatherCaustic_Cube_PS"; passBlendingSRC = SBF_DEST_COLOUR; passBlendingDEST = SBF_ONE; createNewPasses = true; startTextureUnitID = 0; casterCenterVariableName = "cubeMapCameraPosition"; attenuationVariableName = ""; bindDistanceMap = false; parseParams(params); OgreCausticReceiverRenderTechnique* result = new OgreCausticReceiverRenderTechnique( maxcasters, causticVertexProgram, causticFragmentProgram, passBlendingSRC, passBlendingDEST, createNewPasses, startTextureUnitID, casterCenterVariableName, attenuationVariableName, bindDistanceMap, pass, parentRenderable, parentTechniqueGroup); return result; }