source: GTP/trunk/Lib/Illum/IllumModule/OgreIllumModule/src/RenderingRuns/OgreDepthShadowMapRenderingRun.cpp @ 2460

Revision 2460, 15.9 KB checked in by szirmay, 18 years ago (diff)
Line 
1#include "OgreDepthShadowMapRenderingRun.h"
2#include "OgreIlluminationManager.h"
3
4
5OgreDepthShadowMapRenderingRun::OgreDepthShadowMapRenderingRun(OgreSharedRuns* sharedRuns,
6                                                                                                                                String name,
7                                                                                                                                Light* light,
8                                                                                                                                unsigned int resolutionX,
9                                                                                                                                unsigned int resolutionY,
10                                                                                                                                String materialName
11                                                                                                                   )
12                                                                                                                   :DepthShadowMapRenderingRun(resolutionX, resolutionY)
13                                                                                                                   , OgreRenderingRun(1, 1)
14                                                                                                                   , RenderingRun(1, 1)
15{
16        this->light = light;
17        this->sharedRuns = sharedRuns;
18        this->name = name;     
19        this->blurredname = name + "blurred";
20       
21        this->materialName = materialName;
22        lightFarPlane = 0;
23        createDepthMap();       
24}
25
26void OgreDepthShadowMapRenderingRun::createDepthMap()
27{
28        if(light->getType() == Light::LT_POINT)
29        {
30                depthMapTexture = createCubeRenderTexture(name, light->getPosition(), resolutionX,PF_FLOAT16_RGBA,0,ColourValue::White);
31                for(int i = 0; i < 6; i++)
32                        depthMapTexture->getBuffer(i, 0).getPointer()->getRenderTarget()->getViewport(0)->setSkiesEnabled(false);
33               
34                if(OgreIlluminationManager::getSingleton().getBlurShadowMap(light->getType()))
35                blurredDepthMapTexture = createCubeRenderTexture(blurredname, light->getPosition(), resolutionX,PF_FLOAT16_RGBA,0,ColourValue::White);
36        }
37        else
38        {
39       
40                TexturePtr texPtr = Ogre::TextureManager::getSingleton().createManual(name,
41                                                                                                                                                        "default",
42                                                                                                                                                        TEX_TYPE_2D,
43                                                                                                                                                        resolutionX,
44                                                                                                                                                        resolutionY,
45                                                                                                                                                        0,
46                                                                                                                                                        0,
47                                                                                                                                                        PF_FLOAT16_RGBA,
48                                                                                                                                                        TU_RENDERTARGET);               
49                depthMapTexture = texPtr.getPointer();
50                depthMapCamera = Root::getSingleton()._getCurrentSceneManager()->createCamera(name + "_CAMERA");
51                //add viewport to rendertarget
52                HardwarePixelBuffer* hpb = (depthMapTexture->getBuffer()).getPointer();
53                RenderTarget* rt = hpb->getRenderTarget();
54                Viewport* v = rt->addViewport(depthMapCamera);
55                v->setBackgroundColour(ColourValue::White);
56                v->setOverlaysEnabled(false);
57                v->setSkiesEnabled(false);
58                rt->setAutoUpdated(false);
59               
60                if(OgreIlluminationManager::getSingleton().getBlurShadowMap(light->getType()))
61                {
62                        texPtr = Ogre::TextureManager::getSingleton().createManual(blurredname,
63                                                                                                                                                                "default",
64                                                                                                                                                                TEX_TYPE_2D,
65                                                                                                                                                                resolutionX,
66                                                                                                                                                                resolutionY,
67                                                                                                                                                                0,
68                                                                                                                                                                0,
69                                                                                                                                                                PF_FLOAT16_RGBA,
70                                                                                                                                                                TU_RENDERTARGET);
71                        blurredDepthMapTexture = texPtr.getPointer();
72                        hpb = (blurredDepthMapTexture->getBuffer()).getPointer();
73                        rt = hpb->getRenderTarget();
74                        v = rt->addViewport(depthMapCamera);
75                        v->setOverlaysEnabled(false);
76                        rt->setAutoUpdated(false);
77                }
78        }
79}
80
81bool  OgreDepthShadowMapRenderingRun::renderableQueued (Renderable *rend, uint8 groupID, ushort priority, Technique **ppTech)
82{
83        if((*ppTech)->isTransparent())
84                return false;
85
86        if(!rend->getCastsShadows())
87                return false;
88
89        String materialToSet = materialName;
90        OgreTechniqueGroup* TG = (OgreTechniqueGroup*) rend->getRenderTechniqueGroup();
91        if(TG)
92        {
93                String triggeredMaterial = TG->getMaterialNameForTrigger(triggerName);
94                if(triggeredMaterial != "")//a trigger is associated
95                        materialToSet = triggeredMaterial;
96       
97        }       
98       
99        Technique* techn = ((Material*)MaterialManager::getSingleton().getByName(       materialToSet ).getPointer())->getTechnique(0);
100        *ppTech = techn;       
101        return true;
102}
103
104void OgreDepthShadowMapRenderingRun::updateFrame(unsigned long frameNum)
105{
106        refreshLight(frameNum);
107       
108        if(light->getType() == Light::LT_POINT)
109        {               
110               
111                for(int i = 0; i < 6 ; i++)
112                        updateDepthCubeFace(i);         
113
114                //restoreMaterials();
115        }
116        else
117        {
118                updateDepthMap();
119        }       
120
121       
122}
123
124void OgreDepthShadowMapRenderingRun::updateDepthCubeFace(int facenum)
125{       
126        Vector3 lightpos = light->getDerivedPosition();                 
127               
128        RenderTarget* rt = depthMapTexture->getBuffer(facenum, 0).getPointer()->getRenderTarget();     
129        Camera*  cam =  rt->getViewport(0)->getCamera();
130        cam->setFarClipDistance(lightFarPlane);
131        cam->setPosition(lightpos);
132       
133       
134        //setMaterialForVisibles(materialName, cam, true, false, triggerName);
135        RenderQueue* rq = Root::getSingleton()._getCurrentSceneManager()->getRenderQueue();             
136        rq->setRenderableListener(this);
137
138        rt->update();
139
140//      restoreMaterials();
141       
142        //rt->writeContentsToFile("shadowmap_" + StringConverter::toString(facenum) + ".dds");
143
144        rq->setRenderableListener(0);
145
146        if(OgreIlluminationManager::getSingleton().getBlurShadowMap(light->getType()))
147        {
148                rt = blurredDepthMapTexture->getBuffer(facenum, 0).getPointer()->getRenderTarget();
149                Material*  mat = (Material*) MaterialManager::getSingleton().getByName("GameTools/BlurCubeFace").getPointer();
150                mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(depthMapTexture->getName());
151                mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("face", facenum);
152                renderFullscreenQuad("GameTools/BlurCubeFace", rt);             
153               
154                //rt->writeContentsToFile("shadowmap_blurred_" + StringConverter::toString(facenum) + ".dds");
155        }       
156}
157
158void OgreDepthShadowMapRenderingRun::updateDepthMap()
159{
160       
161        RenderTarget* rt = depthMapTexture->getBuffer().getPointer()->getRenderTarget();       
162        Viewport* vp = rt->getViewport(0);
163       
164        //setMaterialForVisibles(materialName, depthMapCamera, true, false, triggerName);       
165        RenderQueue* rq = Root::getSingleton()._getCurrentSceneManager()->getRenderQueue();             
166        rq->setRenderableListener(this);
167
168        rt->update();
169       
170        //restoreMaterials();
171        rq->setRenderableListener(0);
172
173        if(OgreIlluminationManager::getSingleton().getBlurShadowMap(light->getType()))
174        {
175                rt = blurredDepthMapTexture->getBuffer().getPointer()->getRenderTarget();
176                Material*  mat = (Material*) MaterialManager::getSingleton().getByName("GameTools/Blur").getPointer();
177                mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(depthMapTexture->getName());
178                renderFullscreenQuad("GameTools/Blur", rt);
179        }       
180       
181        //rt->writeContentsToFile("shadowmap1.dds");
182
183        //depthMapTexture->();
184}
185
186const String& OgreDepthShadowMapRenderingRun::getDepthMapTextureName()
187{
188                if(OgreIlluminationManager::getSingleton().getBlurShadowMap(light->getType()))
189                        return blurredname;
190
191                return name;
192}
193
194void OgreDepthShadowMapRenderingRun::refreshLight(unsigned long frameNum)
195{
196        if(light!= 0)
197        {
198                bool uselispsm = OgreIlluminationManager::getSingleton().getUseLISPSM(light->getType());
199                bool usefocusing = OgreIlluminationManager::getSingleton().getFocusingShadowMap(light->getType());
200                if(light->getType() == Light::LT_DIRECTIONAL)
201                {
202                        triggerName = "ILLUM_TRIGGER_SM_DIRECTIONAL";
203                        Camera* viewcam = OgreIlluminationManager::getSingleton().getMainCamera();                     
204                       
205                        OgreFocusingMapRenderingRun* frun = (OgreFocusingMapRenderingRun*)
206                                OgreIlluminationManager::getSingleton().getGlobalRun(ILLUMRUN_FOCUSING_MAP)->asOgreRenderingRun();
207                        frun->setCameraMatrices(viewcam->getViewMatrix(), viewcam->getProjectionMatrix());
208
209                        Vector3 lightpos = light->getDerivedPosition();
210                        Vector3 lightdir = light->getDerivedDirection();
211                        lightdir.normalise();           
212                       
213                        Vector3 min;
214                        Vector3 max;                   
215
216                       
217                        if(uselispsm)
218                        {
219                                Camera* maincam = OgreIlluminationManager::getSingleton().getMainCamera();
220                                Vector3 viewdir = maincam->getDirection();
221                                viewdir.normalise();
222                                Vector3 campos = maincam->getPosition();
223                                float nearclip = maincam->getNearClipDistance();
224
225                                float dotprod = viewdir.dotProduct(lightdir);
226                                float sinGamma = sqrt(1.0 - dotprod * dotprod);
227                               
228                                Vector3 left = lightdir.crossProduct(viewdir);
229                                left.normalise();
230                                Vector3 up = left.crossProduct(lightdir);
231                                up.normalise();
232                                //left = lightdir.crossProduct(up);
233                                left.normalise();                               
234                                Matrix4 viewMatrix( left.x,      left.y,      left.z,            0,
235                                                                        up.x,            up.y,            up.z,                  0,
236                                                                        lightdir.x,  lightdir.y,  lightdir.z,    0,
237                                                                        0,           0,           0,             1);                           
238                               
239                                frun->setLightMatrix(viewMatrix);                               
240                                OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
241                                                                                                                                                        frameNum);                     
242                                frun->getMinMax(min, max);
243
244                                float n;
245                                float f;
246                                float d = abs(max.y - min.y);
247                                       
248                                float z_n = nearclip / sinGamma;
249                                float one_min_singamma = (1 - sinGamma);
250                                float fact = d * pow(one_min_singamma, 2);
251                                float z_f = z_n + d * sinGamma * fact;
252                                n = (z_n + sqrt(z_f * z_n)) / sinGamma;
253                                ///n = 100000;
254                                f = n + d;
255
256                                Vector3 pos = campos - up * (n - nearclip);
257                                Matrix4 newViewMatrix(  left.x,      left.y,      left.z,                -left.dotProduct(pos),
258                                                                                up.x,            up.y,            up.z,                  -up.dotProduct(pos),
259                                                                                -lightdir.x,  -lightdir.y,  -lightdir.z,    lightdir.dotProduct(pos),
260                                                                                0,           0,           0,             1);
261
262                                Matrix4 lispMat = Matrix4::IDENTITY;
263                               
264                                lispMat[1][1] = f / (f - n);
265                                lispMat[1][3] = f * n / (f - n);
266                                lispMat[3][1] = 1;
267                                lispMat[3][3] = 0;
268                               
269                                depthMapCamera->setCustomProjectionMatrix(true, Matrix4::IDENTITY);
270                                depthMapCamera->setCustomViewMatrix(true, lispMat * newViewMatrix);
271                        }
272                        else
273                        {
274                                depthMapCamera->setCustomProjectionMatrix(true, Matrix4::IDENTITY);
275                                depthMapCamera->setCustomViewMatrix(false);
276                                depthMapCamera->setPosition(lightpos);
277                                depthMapCamera->setDirection(lightdir);                         
278                        }
279
280
281                        Matrix4 lightMatrix = depthMapCamera->getViewMatrix();
282                        frun->setLightMatrix(lightMatrix);
283                       
284                        OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
285                                                                                                                                                frameNum);
286
287                        frun->getMinMax(min, max);                     
288
289                                               
290                        Vector3 scale = (max - min);
291                        scale *= 1.5; // just for safety
292                        if(uselispsm)
293                                scale.z += 1;
294                        else
295                                scale.z += 1000; //TODO: get scene bounding box to set z scale 
296                        Matrix4 projection = Matrix4::IDENTITY;
297                        Matrix4 trans = Matrix4::IDENTITY;
298                        trans.setTrans(Vector3(-(max.x + min.x) / 2.0,
299                                                                   -(max.y + min.y) / 2.0,
300                                                                   -(max.z + min.z) / 2.0));
301                        Matrix4 scaleM = Matrix4::IDENTITY;
302                        scaleM.setScale(Vector3(2.0 / scale.x, 2.0 / scale.y, -2.0 / scale.z));
303                        projection = scaleM * trans;                   
304                        depthMapCamera->setCustomProjectionMatrix(true, projection);                   
305                }
306                else if(light->getType() == Light::LT_SPOTLIGHT)
307                {
308                        triggerName = "ILLUM_TRIGGER_SM_SPOT";
309                        Camera* viewcam = OgreIlluminationManager::getSingleton().getMainCamera();                     
310                       
311                        OgreFocusingMapRenderingRun* frun = (OgreFocusingMapRenderingRun*)
312                                OgreIlluminationManager::getSingleton().getGlobalRun(ILLUMRUN_FOCUSING_MAP)->asOgreRenderingRun();
313                        frun->setCameraMatrices(viewcam->getViewMatrix(), viewcam->getProjectionMatrix());
314
315                        Vector3 lightpos = light->getDerivedPosition();
316                        Vector3 lightdir = light->getDerivedDirection();
317                        lightdir.normalise();           
318                        Radian lightangle = light->getSpotlightOuterAngle();
319                               
320                        Vector3 min;
321                        Vector3 max;
322                       
323                        if(uselispsm)
324                        {
325                                Camera* maincam = OgreIlluminationManager::getSingleton().getMainCamera();
326                                Vector3 viewdir = maincam->getDirection();
327                                viewdir.normalise();
328                                Vector3 campos = maincam->getPosition();
329                                float nearclip = maincam->getNearClipDistance();
330
331                                float dotprod = viewdir.dotProduct(lightdir);
332                                float sinGamma = sqrt(1.0 - dotprod * dotprod);
333                               
334                                Vector3 left = lightdir.crossProduct(viewdir);
335                                Vector3 up = left.crossProduct(lightdir);
336                                up.normalise();
337                                //left = lightdir.crossProduct(up);
338                                left.normalise();
339                               
340                                depthMapCamera->setCustomProjectionMatrix(false);
341                                depthMapCamera->setProjectionType(PT_PERSPECTIVE);
342                                depthMapCamera->setFOVy(lightangle);
343                                depthMapCamera->setAspectRatio(1);
344                                depthMapCamera->setNearClipDistance(0.1);
345                                depthMapCamera->setFarClipDistance(1.0);
346
347                                Matrix4 projMatrix = depthMapCamera->getProjectionMatrixWithRSDepth();
348
349                                Matrix4 viewMatrix( left.x,      left.y,      left.z,            0,
350                                                                        up.x,            up.y,            up.z,                  0,
351                                                                        -lightdir.x,  -lightdir.y,  -lightdir.z,    0,
352                                                                        0,           0,           0,             1);                           
353                               
354                                frun->setLightMatrix(projMatrix * viewMatrix);                         
355                                OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
356                                                                                                                                                        frameNum);                     
357                                frun->getMinMax(min, max);
358
359                                float n;
360                                float f;
361                                float d = abs(max.y - min.y);
362                                       
363                                float z_n = nearclip / sinGamma;
364                                float one_min_singamma = (1 - sinGamma);
365                                float fact = d * pow(one_min_singamma, 2);
366                                float z_f = z_n + d * sinGamma * fact;
367                                n = (z_n + sqrt(z_f * z_n)) / sinGamma;
368                                ///n = 100000;
369                                f = n + d;
370
371                                Vector3 pos = campos - up * (n - nearclip);
372                                Matrix4 newViewMatrix(  left.x,      left.y,      left.z,                -left.dotProduct(pos),
373                                                                                up.x,            up.y,            up.z,                  -up.dotProduct(pos),
374                                                                                -lightdir.x,  -lightdir.y,  -lightdir.z,    lightdir.dotProduct(pos),
375                                                                                0,           0,           0,             1);
376
377                                Matrix4 lispMat = Matrix4::IDENTITY;
378                               
379                                lispMat[1][1] = f / (f - n);
380                                lispMat[1][3] = f * n / (f - n);
381                                lispMat[3][1] = 1;
382                                lispMat[3][3] = 0;
383                               
384                                depthMapCamera->setCustomProjectionMatrix(true, Matrix4::IDENTITY);
385                                depthMapCamera->setCustomViewMatrix(true, lispMat * projMatrix * newViewMatrix);
386                        }
387                        else
388                        {
389                                depthMapCamera->setCustomProjectionMatrix(false);
390                                depthMapCamera->setCustomViewMatrix(false);
391                                depthMapCamera->setPosition(lightpos);
392                                depthMapCamera->setDirection(lightdir);
393                                depthMapCamera->setProjectionType(PT_PERSPECTIVE);
394                                depthMapCamera->setFOVy(lightangle);
395                                depthMapCamera->setAspectRatio(1);
396                                depthMapCamera->setNearClipDistance(OgreIlluminationManager::getSingleton().getAreaLightRadius());
397                                depthMapCamera->setFarClipDistance(1.0);
398                        }
399                       
400                        if(!usefocusing)
401                        {
402                                lightFarPlane = light->getAttenuationRange();
403                                depthMapCamera->setFarClipDistance(lightFarPlane);
404                               
405                        }
406                        else
407                        {
408                                Matrix4 lightMatrix = depthMapCamera->getViewMatrix();
409                                frun->setLightMatrix(lightMatrix);
410                               
411                                OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
412                                                                                                                                                        frameNum);
413
414                                frun->getMinMax(min, max);                     
415                               
416                                if(min.z < 0)
417                                {
418                                        float farP= -1.5 * min.z;
419                                        if(farP < 0.2) farP = 0.2;
420                                                depthMapCamera->setFarClipDistance(farP);
421                                        lightFarPlane = farP;
422                               
423                                        Vector3 scale = (max - min);
424                                        scale *= 1.5; // just for safety
425                                       
426                                        Matrix4 projection = Matrix4::IDENTITY;
427                                        Matrix4 trans = Matrix4::IDENTITY;
428                                        trans.setTrans(Vector3(-(max.x + min.x) / 2.0,
429                                                                        -(max.y + min.y) / 2.0,
430                                                                                0));
431                                        Matrix4 scaleM = Matrix4::IDENTITY;
432                                        scaleM.setScale(Vector3(2.0 / scale.x, 2.0 / scale.y, 1));
433                                        projection = scaleM * trans;                   
434                                        depthMapCamera->setCustomProjectionMatrix(true, projection * depthMapCamera->getProjectionMatrix());                                           
435                                }
436                        }
437                }
438                else//point light
439                {
440                        lightFarPlane = light->getAttenuationRange();
441                        triggerName = "ILLUM_TRIGGER_SM_POINT";         
442                        //no other adjustment needed                   
443                }
444        }
445}
446
447Matrix4 OgreDepthShadowMapRenderingRun::getLightViewMatrix()
448{
449        Camera* cam = depthMapCamera;
450        if(light->getType() == Light::LT_POINT)
451         cam = depthMapTexture->getBuffer(4, 0).getPointer()->getRenderTarget()->getViewport(0)->getCamera();   
452       
453        return cam->getViewMatrix();
454}
455
456Matrix4 OgreDepthShadowMapRenderingRun::getLightViewProjMatrix()
457{
458        Camera* cam = depthMapCamera;
459        if(light->getType() == Light::LT_POINT)
460         cam = depthMapTexture->getBuffer(4, 0).getPointer()->getRenderTarget()->getViewport(0)->getCamera();   
461       
462        return cam->getProjectionMatrixWithRSDepth() * cam->getViewMatrix();
463}
464
465void OgreDepthShadowMapRenderingRun::freeAllResources()
466{
467        this->blurredDepthMapTexture = 0;
468        this->depthMapTexture = 0;
469        TextureManager::getSingleton().remove(name);
470        TextureManager::getSingleton().remove(blurredname);
471        Root::getSingleton()._getCurrentSceneManager()->destroyCamera(name + "_CAMERA");       
472}
Note: See TracBrowser for help on using the repository browser.