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

Revision 2551, 16.3 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        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                                depthMapCamera->setCustomProjectionMatrix(true, lispMat);
273                                depthMapCamera->setCustomViewMatrix(true, newViewMatrix);
274                        }
275                        else
276                        {
277                                depthMapCamera->setCustomProjectionMatrix(true, Matrix4::IDENTITY);
278                                depthMapCamera->setCustomViewMatrix(false);
279                                depthMapCamera->setPosition(lightpos);
280                                depthMapCamera->setDirection(lightdir);                         
281                        }
282
283
284                        Matrix4 lightMatrix = depthMapCamera->getViewMatrix();
285                        //frun->setLightMatrix(lightMatrix);
286                        frun->setLightMatrix(depthMapCamera->getProjectionMatrix() * lightMatrix);
287                       
288                        OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
289                                                                                                                                                frameNum);
290
291                        frun->getMinMax(min, max);                     
292
293                                               
294                        Vector3 scale = (max - min);
295                        scale *= 1.5; // just for safety
296                        if(uselispsm)
297                                scale.z += 1;
298                        else
299                                scale.z += 1000; //TODO: get scene bounding box to set z scale 
300                        Matrix4 projection = Matrix4::IDENTITY;
301                        Matrix4 trans = Matrix4::IDENTITY;
302                        trans.setTrans(Vector3(-(max.x + min.x) / 2.0,
303                                                                   -(max.y + min.y) / 2.0,
304                                                                   -(max.z + min.z) / 2.0));
305                        Matrix4 scaleM = Matrix4::IDENTITY;
306                        scaleM.setScale(Vector3(2.0 / scale.x, 2.0 / scale.y, -2.0 / scale.z));
307                        projection = scaleM * trans;                   
308                        //depthMapCamera->setCustomProjectionMatrix(true, projection); 
309                        lightFarPlane = scale.z;
310                        depthMapCamera->setCustomProjectionMatrix(true, projection * depthMapCamera->getProjectionMatrix());                   
311                }
312                else if(light->getType() == Light::LT_SPOTLIGHT)
313                {
314                        triggerName = "ILLUM_TRIGGER_SM_SPOT";
315                        Camera* viewcam = OgreIlluminationManager::getSingleton().getMainCamera();                     
316                       
317                        OgreFocusingMapRenderingRun* frun = (OgreFocusingMapRenderingRun*)
318                                OgreIlluminationManager::getSingleton().getGlobalRun(ILLUMRUN_FOCUSING_MAP)->asOgreRenderingRun();
319                        frun->setCameraMatrices(viewcam->getViewMatrix(), viewcam->getProjectionMatrix());
320
321                        Vector3 lightpos = light->getDerivedPosition();
322                        Vector3 lightdir = light->getDerivedDirection();
323                        lightdir.normalise();           
324                        Radian lightangle = light->getSpotlightOuterAngle();
325                               
326                        Vector3 min;
327                        Vector3 max;
328                       
329                        if(uselispsm)
330                        {
331                                Camera* maincam = OgreIlluminationManager::getSingleton().getMainCamera();
332                                Vector3 viewdir = maincam->getDirection();
333                                viewdir.normalise();
334                                Vector3 campos = maincam->getPosition();
335                                float nearclip = maincam->getNearClipDistance();
336
337                                float dotprod = viewdir.dotProduct(lightdir);
338                                float sinGamma = sqrt(1.0 - dotprod * dotprod);
339                               
340                                Vector3 left = lightdir.crossProduct(viewdir);
341                                Vector3 up = left.crossProduct(lightdir);
342                                up.normalise();
343                                //left = lightdir.crossProduct(up);
344                                left.normalise();
345                               
346                                depthMapCamera->setCustomProjectionMatrix(false);
347                                depthMapCamera->setProjectionType(PT_PERSPECTIVE);
348                                depthMapCamera->setFOVy(lightangle);
349                                depthMapCamera->setAspectRatio(1);
350                                depthMapCamera->setNearClipDistance(0.1);
351                                depthMapCamera->setFarClipDistance(1.0);
352
353                                Matrix4 projMatrix = depthMapCamera->getProjectionMatrixWithRSDepth();
354
355                                Matrix4 viewMatrix( left.x,      left.y,      left.z,            0,
356                                                                        up.x,            up.y,            up.z,                  0,
357                                                                        -lightdir.x,  -lightdir.y,  -lightdir.z,    0,
358                                                                        0,           0,           0,             1);                           
359                               
360                                frun->setLightMatrix(projMatrix * viewMatrix);                         
361                                OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
362                                                                                                                                                        frameNum);                     
363                                frun->getMinMax(min, max);
364
365                                float n;
366                                float f;
367                                float d = abs(max.y - min.y);
368                                       
369                                float z_n = nearclip / sinGamma;
370                                float one_min_singamma = (1 - sinGamma);
371                                float fact = d * pow(one_min_singamma, 2);
372                                float z_f = z_n + d * sinGamma * fact;
373                                n = (z_n + sqrt(z_f * z_n)) / sinGamma;
374                                ///n = 100000;
375                                f = n + d;
376
377                                Vector3 pos = campos - up * (n - nearclip);
378                                Matrix4 newViewMatrix(  left.x,      left.y,      left.z,                -left.dotProduct(pos),
379                                                                                up.x,            up.y,            up.z,                  -up.dotProduct(pos),
380                                                                                -lightdir.x,  -lightdir.y,  -lightdir.z,    lightdir.dotProduct(pos),
381                                                                                0,           0,           0,             1);
382
383                                Matrix4 lispMat = Matrix4::IDENTITY;
384                               
385                                lispMat[1][1] = f / (f - n);
386                                lispMat[1][3] = f * n / (f - n);
387                                lispMat[3][1] = 1;
388                                lispMat[3][3] = 0;
389                               
390                                depthMapCamera->setCustomProjectionMatrix(true, Matrix4::IDENTITY);
391                                depthMapCamera->setCustomViewMatrix(true, lispMat * projMatrix * newViewMatrix);
392                        }
393                        else
394                        {
395                                depthMapCamera->setCustomProjectionMatrix(false);
396                                depthMapCamera->setCustomViewMatrix(false);
397                                depthMapCamera->setPosition(lightpos);
398                                depthMapCamera->setDirection(lightdir);
399                                depthMapCamera->setProjectionType(PT_PERSPECTIVE);
400                                depthMapCamera->setFOVy(lightangle);
401                                depthMapCamera->setAspectRatio(1);
402                                depthMapCamera->setNearClipDistance(OgreIlluminationManager::getSingleton().getAreaLightRadius());
403                                depthMapCamera->setFarClipDistance(1.0);
404                        }
405                       
406                        if(!usefocusing)
407                        {
408                                lightFarPlane = light->getAttenuationRange();
409                                depthMapCamera->setFarClipDistance(lightFarPlane);
410                               
411                        }
412                        else
413                        {
414                                Matrix4 lightMatrix = depthMapCamera->getViewMatrix();
415                                frun->setLightMatrix(lightMatrix);
416                               
417                                OgreIlluminationManager::getSingleton().updateGlobalRun( ILLUMRUN_FOCUSING_MAP,
418                                                                                                                                                        frameNum);
419
420                                frun->getMinMax(min, max);                     
421                               
422                                if(min.z < 0)
423                                {
424                                        float farP= -1.5 * min.z;
425                                        if(farP < 0.2) farP = 0.2;
426                                                depthMapCamera->setFarClipDistance(farP);
427                                        lightFarPlane = farP;
428                               
429                                        Vector3 scale = (max - min);
430                                        scale *= 1.5; // just for safety
431                                       
432                                        Matrix4 projection = Matrix4::IDENTITY;
433                                        Matrix4 trans = Matrix4::IDENTITY;
434                                        trans.setTrans(Vector3(-(max.x + min.x) / 2.0,
435                                                                        -(max.y + min.y) / 2.0,
436                                                                                0));
437                                        Matrix4 scaleM = Matrix4::IDENTITY;
438                                        scaleM.setScale(Vector3(2.0 / scale.x, 2.0 / scale.y, 1));
439                                        projection = scaleM * trans;                   
440                                        depthMapCamera->setCustomProjectionMatrix(true, projection * depthMapCamera->getProjectionMatrix());                                           
441                                }
442                        }
443                }
444                else//point light
445                {
446                        lightFarPlane = light->getAttenuationRange();
447                        triggerName = "ILLUM_TRIGGER_SM_POINT";         
448                        //no other adjustment needed                   
449                }
450        }
451}
452
453Matrix4 OgreDepthShadowMapRenderingRun::getLightViewMatrix()
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->getViewMatrix();
460}
461
462Matrix4 OgreDepthShadowMapRenderingRun::getLightViewProjMatrix()
463{
464        Camera* cam = depthMapCamera;
465        if(light->getType() == Light::LT_POINT)
466         cam = depthMapTexture->getBuffer(4, 0).getPointer()->getRenderTarget()->getViewport(0)->getCamera();   
467       
468        return cam->getProjectionMatrixWithRSDepth() * cam->getViewMatrix();
469}
470
471void OgreDepthShadowMapRenderingRun::freeAllResources()
472{
473        this->blurredDepthMapTexture = 0;
474        this->depthMapTexture = 0;
475        TextureManager::getSingleton().remove(name);
476        TextureManager::getSingleton().remove(blurredname);
477        Root::getSingleton()._getCurrentSceneManager()->destroyCamera(name + "_CAMERA");       
478}
Note: See TracBrowser for help on using the repository browser.