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

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