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

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