#include "OgreLightVolumeRenderingRun.h" #include "OgreIlluminationManager.h" #include "OgreChildPSystemRenderingRun.h" OgreLightVolumeRenderingRun::OgreLightVolumeRenderingRun(OgreSharedRuns* sharedRuns, String name, unsigned long startFrame, unsigned long updateInterval, unsigned int resolution, unsigned int textureDepth, String materialName ) :LightVolumeRenderingRun( startFrame, updateInterval, resolution, textureDepth) , OgreRenderingRun(startFrame, updateInterval) , RenderingRun(startFrame, updateInterval) { this->sharedRuns = sharedRuns; this->name = name; this->light = 0; this->materialName = materialName; volumeBuffer = 0; createLightVolumeMap(); } void OgreLightVolumeRenderingRun::createLightVolumeMap() { TexturePtr texPtr = Ogre::TextureManager::getSingleton().createManual(name + "NoBlur", "default", TEX_TYPE_2D, resolution, resolution, 0, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET); lightVolumeTexture = texPtr.getPointer(); lightVolumeCamera = Root::getSingleton()._getCurrentSceneManager()->createCamera(name + "_CAMERA"); //add viewport to rendertarget HardwarePixelBuffer* hpb = (lightVolumeTexture->getBuffer()).getPointer(); RenderTarget* rt = hpb->getRenderTarget(); Viewport* v = rt->addViewport(lightVolumeCamera); //Viewport* v = rt->addViewport(OgreIlluminationManager::getSingleton().getMainCamera()); v->setOverlaysEnabled(false); v->setBackgroundColour(ColourValue::White); rt->setAutoUpdated(false); texPtr = Ogre::TextureManager::getSingleton().createManual(name, "default", TEX_TYPE_2D, resolution, resolution, 0, 0, PF_FLOAT16_RGBA, TU_RENDERTARGET); lightVolumeTexture2 = texPtr.getPointer(); hpb = (lightVolumeTexture2->getBuffer()).getPointer(); rt = hpb->getRenderTarget(); v = rt->addViewport(lightVolumeCamera); v->setOverlaysEnabled(false); v->setBackgroundColour(ColourValue::White); rt->setAutoUpdated(false); v->setClearEveryFrame(true); SceneManager* sm = Root::getSingleton()._getCurrentSceneManager(); RenderQueue *rq = sm->getRenderQueue(); sm->setFindVisibleObjects(false); rq->clear(); v->update(); sm->setFindVisibleObjects(true); v->setClearEveryFrame(false); if(textureDepth > 1) { TexturePtr texPtr3D = Ogre::TextureManager::getSingleton().createManual(name + "3D", "default", TEX_TYPE_3D, resolution, resolution, textureDepth + 1, 0, PF_FLOAT16_RGBA, TU_DYNAMIC); lightVolumeTexture3D = texPtr3D.getPointer(); } } void OgreLightVolumeRenderingRun::createVolumeBuffer() { unsigned int buffersize = resolution * resolution * 4 * 2 * (textureDepth + 1); volumeBuffer = new unsigned char[buffersize]; SceneManager* sm = Ogre::Root::getSingleton()._getCurrentSceneManager(); RenderQueue* rq = sm->getRenderQueue(); RenderTarget* rt = lightVolumeTexture->getBuffer().getPointer()->getRenderTarget(); rq->clear(); //clear screen sm->setFindVisibleObjects(false); rt->update(); sm->setFindVisibleObjects(true); //copy first slice PixelBox volumePB(resolution, resolution, 3,PF_FLOAT16_RGBA, volumeBuffer); PixelBox pb(resolution, resolution, 1,PF_FLOAT16_RGBA, volumeBuffer); lightVolumeTexture->getBuffer()->blitToMemory(pb); lightVolumeTexture3D->getBuffer()->blitFromMemory(volumePB); } void OgreLightVolumeRenderingRun::updateFrame(unsigned long frameNum) { if(textureDepth > 1 && volumeBuffer == 0) createVolumeBuffer(); refreshLight(); SceneManager* sm = Ogre::Root::getSingleton()._getCurrentSceneManager(); RenderQueue* rq = sm->getRenderQueue(); rq->clear(); //((OgreSharedRuns*)sharedRuns->getRoot(ILLUMRUN_LIGHTVOLUME_MAP))->notifyCamera(lightVolumeCamera); ((OgreSharedRuns*)sharedRuns->getRoot(ILLUMRUN_LIGHTVOLUME_MAP))->addRenderablesToQueue(rq, false); setMaterialForRenderables(materialName,rq); if(textureDepth == 1) { RenderTarget* rt = lightVolumeTexture->getBuffer().getPointer()->getRenderTarget(); rt->update(); restoreMaterials(); //do blending rt = lightVolumeTexture2->getBuffer().getPointer()->getRenderTarget(); Material* mat = (Material*) MaterialManager::getSingleton().getByName("GameTools/BlurLightVolume").getPointer(); mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(lightVolumeTexture->getName()); renderFullscreenQuad("GameTools/BlurLightVolume", rt); /* static int framecount = 0; String filename = "lightvolume"; filename.append(this->name); //filename.append(StringConverter::toString(framecount)); filename.append(".bmp"); if(framecount % 5 == 0) rt->writeContentsToFile(filename); framecount++;*/ } else { //for(unsigned int i = 0; i < textureDepth; i++) unsigned int i = frameNum % textureDepth; { //set camera nearplane Matrix4 proj; proj = Matrix4::IDENTITY; float fustrumDepth = (i + 1) * systemRadius / ((float) textureDepth); proj.setScale(Vector3(1.0 / systemRadius, 1.0 / systemRadius, -2.0 / fustrumDepth)); proj.setTrans(Vector3(0,0,-1)); lightVolumeCamera->setCustomProjectionMatrix(true,proj); //render RenderTarget* rt = lightVolumeTexture->getBuffer().getPointer()->getRenderTarget(); rt->update(); //copy texture data PixelBox volumePB(resolution, resolution, textureDepth, PF_FLOAT16_RGBA, volumeBuffer); PixelBox pb(resolution, resolution, 1,PF_FLOAT16_RGBA, volumeBuffer + (i + 1) * resolution * resolution * 4 * 2); lightVolumeTexture->getBuffer()->blitToMemory(pb); lightVolumeTexture3D->getBuffer()->blitFromMemory(volumePB); } restoreMaterials(); } /* PixelBox volumePB(resolution, resolution, 3,PF_FLOAT16_RGBA, volumeBuffer); PixelBox pb(resolution, resolution, 1,PF_FLOAT16_RGBA, volumeBuffer); lightVolumeTexture->getBuffer()->blitToMemory(pb); lightVolumeTexture3D->getBuffer()->blitFromMemory(volumePB); */ } void OgreLightVolumeRenderingRun::refreshLight() { SceneManager* sm = Root::getSingleton()._getCurrentSceneManager(); LightList list; sm->_populateLightList(((OgreSharedRuns*)sharedRuns)->getRootPosition(ILLUMRUN_LIGHTVOLUME_MAP),100000, list); light = *(list.begin()); //if herarchical float baseRad = 0.0; RenderingRun* run = sharedRuns->getRun(ILLUMRUN_HPP_IMPOSTOR); if( run != 0) { OgreChildPSystemRenderingRun* rrun = (OgreChildPSystemRenderingRun*) run->asOgreRenderingRun(); baseRad = rrun->getSmallSysRadius(); //set gpu program params Material* m = (Material*) MaterialManager::getSingleton().getByName(materialName).getPointer(); GpuProgramParametersSharedPtr vp = m->getTechnique(0)->getPass(0)->getVertexProgramParameters(); vp->setNamedConstant("baseRadius",baseRad); } if(light!= 0) { if(light->getType() == Light::LT_DIRECTIONAL) { Vector3 dir = light->getDirection(); dir.normalise(); lightVolumeCamera->setDirection( dir ); Real r = sharedRuns->getRootBoundingSphere(ILLUMRUN_LIGHTVOLUME_MAP).getRadius(); r += baseRad; systemRadius = r; lightVolumeCamera->setPosition( sharedRuns->getRootPosition(ILLUMRUN_LIGHTVOLUME_MAP) - dir * r); lightVolumeCamera->setProjectionType(PT_ORTHOGRAPHIC); Matrix4 proj; proj = Matrix4::IDENTITY; proj.setScale(Vector3(1.0/r, 1.0/r, -1.0/r)); proj.setTrans(Vector3(0,0,-1)); lightVolumeCamera->setCustomProjectionMatrix(true,proj); } else { Vector3 pos = light->getDerivedPosition(); Vector3 dir = sharedRuns->getRootPosition(ILLUMRUN_LIGHTVOLUME_MAP) - pos; dir.normalise(); Real r = sharedRuns->getRootBoundingSphere(ILLUMRUN_LIGHTVOLUME_MAP).getRadius(); r += baseRad; lightVolumeCamera->setPosition( sharedRuns->getRootPosition(ILLUMRUN_LIGHTVOLUME_MAP) - dir * r); lightVolumeCamera->lookAt( sharedRuns->getRootPosition(ILLUMRUN_LIGHTVOLUME_MAP) ); lightVolumeCamera->setProjectionType(PT_ORTHOGRAPHIC); Matrix4 proj; proj = Matrix4::IDENTITY; proj.setScale(Vector3(1.0/r, 1.0/r, -1/r)); proj.setTrans(Vector3(0,0,-1)); lightVolumeCamera->setCustomProjectionMatrix(true,proj); } } } void OgreLightVolumeRenderingRun::freeAllResources() { this->lightVolumeTexture = 0; this->lightVolumeTexture2 = 0; this->lightVolumeTextureLast = 0; this->lightVolumeTextureThis = 0; this->lightVolumeTexture3D = 0; TextureManager::getSingleton().remove(name); TextureManager::getSingleton().remove(name + "NoBlur"); Root::getSingleton()._getCurrentSceneManager()->destroyCamera(name + "_CAMERA"); }