#include "OgrePathMapRenderTechnique.h" #include "OgreTechniqueGroup.h" #include "OgreIlluminationManager.h" #include "OgrePMWeightComputeRenderingRun.h" OgrePathMapRenderTechnique::OgrePathMapRenderTechnique( SceneBlendFactor passBlendingSRC, SceneBlendFactor passBlendingDEST, bool createNewPasses, int startTextureUnitID, Pass* pass, OgreRenderable* parentRenderable, OgreTechniqueGroup* parentTechniqueGroup) :RenderTechnique( parentRenderable, parentTechniqueGroup), OgreRenderTechnique(pass, parentRenderable, parentTechniqueGroup) { this->passBlendingSRC = passBlendingSRC; this->passBlendingDEST = passBlendingDEST; this->createNewPasses = createNewPasses; this->startTextureUnitID = startTextureUnitID; this->clusters = OgreIlluminationManager::getSingleton().getPathMapClusters(parentRenderable->getName()); Pass* passToSet = pass; //insert new pass if(createNewPasses) { Ogre::Technique* techn = pass->getParent(); Technique::PassIterator it = techn->getPassIterator(); int index = 0; while(it.hasMoreElements()) { if( it.getNext() == pass) break; index++; it.moveNext(); } Pass* newpass = pathMapPass = passToSet = techn->createPass(); newpass->setVertexProgram("GTP/PathMap_VS"); newpass->setFragmentProgram("GTP/PathMap_PS"); GpuProgramParameters* Vparams = passToSet->getVertexProgramParameters().getPointer(); Vparams->setNamedAutoConstant("WorldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); } //bind fragment program parameters GpuProgramParameters* Fparams = passToSet->getFragmentProgramParameters().getPointer(); int prmxres = this->clusters->pathMapResolution * this->clusters->count; int prmyres = this->clusters->pathMapResolution; while(prmxres > 4096) { prmxres /= 2; prmyres *= 2; } int prmnt[2] = {prmxres / this->clusters->pathMapResolution, prmyres / this->clusters->pathMapResolution}; float halfPixel[2] = {0.5 / prmxres, 0.5 / prmyres}; Vector4 pathMapParameters(prmnt[0],prmnt[1],halfPixel[0],halfPixel[1]); Fparams->setNamedConstant("prmAtlasTilesHalfPixel",pathMapParameters); unsigned int clustercount = OgreIlluminationManager::getSingleton().getPathMapClusterLengthsSize(); Fparams->setNamedConstant("allClusterCount", (float) clustercount); PathMapClusters* clusters = OgreIlluminationManager::getSingleton().getPathMapClusters(parentOgreRenderable->getName()); Fparams->setNamedConstant("clusterCount", (float) clusters->count); TextureUnitState* st1;//path map texture TextureUnitState* st2;//weight index texture TextureUnitState* st3;//weight texture createWeightIndexTexture(); if(createNewPasses) { st1 = passToSet->createTextureUnitState(); st1->setTextureFiltering(TFO_BILINEAR); st1->setTextureAddressingMode(TextureUnitState::TAM_BORDER); st1->setTextureBorderColour(ColourValue::Green); st2 = passToSet->createTextureUnitState(); st2->setTextureFiltering(TFO_NONE); st2->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); st2->setTextureBorderColour(ColourValue::Red); st3 = passToSet->createTextureUnitState(); st3->setTextureFiltering(TFO_NONE); st3->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); st3->setTextureBorderColour(ColourValue::Blue); TextureUnitState* st4 = passToSet->createTextureUnitState(); st4->setTextureFiltering(TFO_BILINEAR); st4->setTextureAddressingMode(TextureUnitState::TAM_WRAP); st4->setTextureBorderColour(ColourValue::Blue); st4->setTextureName(pass->getTextureUnitState(0)->getTextureName()); passToSet->setSceneBlending(passBlendingSRC, passBlendingDEST); passToSet->setDepthBias(1); } else { st1 = pass->getTextureUnitState(startTextureUnitID); st2 = pass->getTextureUnitState(startTextureUnitID + 1); st3 = pass->getTextureUnitState(startTextureUnitID + 2); } st1->setTextureName(clusters->pathMapTextureFilename); st2->setTextureName(weightIndexTexture->getName()); } OgrePathMapRenderTechnique::~OgrePathMapRenderTechnique() { } void OgrePathMapRenderTechnique::createWeightIndexTexture() { PathMapClusters* clusters = OgreIlluminationManager::getSingleton().getPathMapClusters(parentOgreRenderable->getName()); int width = clusters->count; TexturePtr texPtr = Ogre::TextureManager::getSingleton().createManual(this->parentOgreRenderable->getName() + "_PMWeightIndexTexture", "default", TEX_TYPE_2D, width, 1, 0, 0, PF_FLOAT32_R, TU_DYNAMIC_WRITE_ONLY); weightIndexTexture = texPtr.getPointer(); float *weightIndices = new float[width]; PixelBox lockBox(width, 1, 1, PF_FLOAT32_R, weightIndices); for(int j = 0; j< clusters->count; j++) weightIndices[j] = clusters->clusters[j]; weightIndexTexture->getBuffer()->blitFromMemory(lockBox); delete[] weightIndices; } void OgrePathMapRenderTechnique::update(unsigned long frameNum) { LightList lights; SceneManager* sm = Root::getSingleton()._getCurrentSceneManager(); sm->_populateLightList(OgreIlluminationManager::getSingleton().getMainCamera()->getPosition(), 1000, lights); int found = 0; for(int i = 0 ; found < 5 && i < lights.size(); i++) { if(lights.at(i)->isAttached()) { found ++; String lightName = lights.at(i)->getName(); OgreIlluminationManager::getSingleton().createPerLightRun(lightName, ILLUMRUN_PM_WEIGHTMAP); OgreIlluminationManager::getSingleton().updatePerLightRun(lightName, ILLUMRUN_PM_WEIGHTMAP, frameNum); } } OgrePMWeightComputeRenderingRun::sumWeights(frameNum); Pass* passToSet = pass; int textureUnitID = startTextureUnitID + 2; if(createNewPasses) { passToSet = pathMapPass; textureUnitID = 2; } TextureUnitState* st = passToSet->getTextureUnitState(textureUnitID); st->setTextureName(OgrePMWeightComputeRenderingRun::getPMWeightTextureName()); } namespace PathMapParsers { 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) { OgrePathMapRenderTechniqueFactory* f = (OgrePathMapRenderTechniqueFactory*) 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) { OgrePathMapRenderTechniqueFactory* f = (OgrePathMapRenderTechniqueFactory*) factory; f->createNewPasses = StringConverter::parseBool(params); } void parseStartTexID(String& params, RenderTechniqueFactory* factory) { OgrePathMapRenderTechniqueFactory* f = (OgrePathMapRenderTechniqueFactory*) factory; f->startTextureUnitID = StringConverter::parseInt(params); } } OgrePathMapRenderTechniqueFactory::OgrePathMapRenderTechniqueFactory() { typeName = "PathMap"; using namespace PathMapParsers; 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)); } OgreRenderTechnique* OgrePathMapRenderTechniqueFactory::createInstance( IllumTechniqueParams* params, Pass* pass, OgreRenderable* parentRenderable, OgreTechniqueGroup* parentTechniqueGroup) { passBlendingSRC = SBF_ONE; passBlendingDEST = SBF_ONE; createNewPasses = true; startTextureUnitID = 0; parseParams(params); OgrePathMapRenderTechnique* result = new OgrePathMapRenderTechnique( passBlendingSRC, passBlendingDEST, createNewPasses, startTextureUnitID, pass, parentRenderable, parentTechniqueGroup); return result; }