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

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