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

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