source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/ShadowMapping.cpp @ 3001

Revision 3001, 17.6 KB checked in by mattausch, 16 years ago (diff)

reverted back from trying to use less components in fbo for faster sampling

RevLine 
[2891]1#include "ShadowMapping.h"
2#include "FrameBufferObject.h"
3#include "RenderState.h"
4#include "RenderTraverser.h"
5#include "Light.h"
[2911]6#include "Polygon3.h"
7#include "Polyhedron.h"
8
[2891]9#include <IL/il.h>
10#include <assert.h>
11
[2911]12
[2891]13using namespace std;
14
15
16namespace CHCDemoEngine
17{
18
[2931]19static CGprogram sCgShadowProgram;
20static CGparameter sShadowParam;
[2891]21
[2931]22
[2911]23static Polyhedron *polyhedron = NULL;
[2929]24static Polyhedron *lightPoly = NULL;
[2911]25
26
[2891]27static void PrintGLerror(char *msg)
28{
29        GLenum errCode;
30        const GLubyte *errStr;
31       
32        if ((errCode = glGetError()) != GL_NO_ERROR)
33        {
34                errStr = gluErrorString(errCode);
35                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
36        }
37}
38
39
[2936]40static Polyhedron *CreatePolyhedron(const Matrix4x4 &lightMatrix,
41                                                                        const AxisAlignedBox3 &sceneBox)
[2931]42{
43        Frustum frustum(lightMatrix);
[2891]44
[2931]45        vector<Plane3> clipPlanes;
[2891]46
[2931]47        for (int i = 0; i < 6; ++ i)
48        {
49                ////////////
50                //-- normalize the coefficients
[2891]51
[2931]52                // the clipping planes look outward the frustum,
53                // so distances > 0 mean that a point is outside
54                const float invLength = -1.0f / Magnitude(frustum.mClipPlanes[i].mNormal);
55
56                frustum.mClipPlanes[i].mD *= invLength;
57                frustum.mClipPlanes[i].mNormal *= invLength;
58        }
59
[2939]60        // first create near plane because of precision issues
61        clipPlanes.push_back(frustum.mClipPlanes[4]);
62
[2931]63        clipPlanes.push_back(frustum.mClipPlanes[0]);
64        clipPlanes.push_back(frustum.mClipPlanes[1]);
65        clipPlanes.push_back(frustum.mClipPlanes[2]);
66        clipPlanes.push_back(frustum.mClipPlanes[3]);
[2936]67        clipPlanes.push_back(frustum.mClipPlanes[5]);
68
[2931]69        return Polyhedron::CreatePolyhedron(clipPlanes, sceneBox);
70}
71
72
[2891]73static void GrabDepthBuffer(float *data, GLuint depthTexture)
74{
75        glEnable(GL_TEXTURE_2D);
76        glBindTexture(GL_TEXTURE_2D, depthTexture);
77
78        glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, data);
79
80        glBindTexture(GL_TEXTURE_2D, 0);
81        glDisable(GL_TEXTURE_2D);
82}
83
84
85static void ExportDepthBuffer(float *data, int size)
86{
87        ilInit();
88        assert(ilGetError() == IL_NO_ERROR);
89
90        ILstring filename = ILstring("shadow.tga");
91        ilRegisterType(IL_FLOAT);
92
93        const int depth = 1;
94        const int bpp = 1;
95
96        if (!ilTexImage(size, size, depth, bpp, IL_LUMINANCE, IL_FLOAT, data))
97        {
98                cerr << "IL error " << ilGetError() << endl;
99       
100                ilShutDown();
101                assert(ilGetError() == IL_NO_ERROR);
102
103                return;
104        }
105
106        if (!ilSaveImage(filename))
107        {
108                cerr << "TGA write error " << ilGetError() << endl;
109        }
110
111        ilShutDown();
112        assert(ilGetError() == IL_NO_ERROR);
113
114        cout << "exported depth buffer" << endl;
115}
116
117
118
[2924]119static AxisAlignedBox3 GetExtremalPoints(const Matrix4x4 &m,
120                                                                                 const VertexArray &pts)
121{
122        AxisAlignedBox3 extremalPoints;
123        extremalPoints.Initialize();
124
125        VertexArray::const_iterator it, it_end = pts.end();
126               
127        for (it = pts.begin(); it != it_end; ++ it)
128        {
129                Vector3 pt = *it;
130                pt = m * pt;
131
132                extremalPoints.Include(pt);
133        }
134
135        return extremalPoints;
136}
137
138
[2952]139ShadowMap::ShadowMap(DirectionalLight *light, int size, const AxisAlignedBox3 &sceneBox, Camera *cam):
[2897]140mSceneBox(sceneBox), mSize(size), mCamera(cam), mLight(light)
[2891]141{
142        mFbo = new FrameBufferObject(size, size, FrameBufferObject::DEPTH_32, true);
[2965]143
[2947]144        // need a color buffer to keep opengl happy
[3001]145        mFbo->AddColorBuffer(ColorBufferObject::RGBA_UBYTE,
[2965]146                                 ColorBufferObject::WRAP_CLAMP_TO_EDGE,
147                                                 ColorBufferObject::FILTER_NEAREST);
[2891]148
[2965]149
[2947]150        mShadowCam = new Camera(mSize, mSize);
[2891]151        mShadowCam->SetOrtho(true);
152}
153
154
[2894]155ShadowMap::~ShadowMap()
[2891]156{
157        DEL_PTR(mFbo);
[2897]158        DEL_PTR(mShadowCam);
[2891]159}
160
161
[2963]162static void DrawPolyhedron(Polyhedron *poly, const Vector3 &color)
[2891]163{
[2929]164        if (!poly) return;
[2911]165
[2929]166        for (size_t i = 0; i < poly->NumPolygons(); ++ i)
[2911]167        {
[2929]168                glColor3f(color.x, color.y, color.z);
[2911]169
170                glBegin(GL_LINE_LOOP);
171
[2929]172                Polygon3 *p = poly->GetPolygons()[i];
[2911]173
[2929]174                for (size_t j = 0; j < p->mVertices.size(); ++ j)
[2911]175                {
[2929]176                        Vector3 v = p->mVertices[j];
[2911]177                        glVertex3d(v.x, v.y, v.z);
178                }
179
180                glEnd();
181        }
182}
183
184
[2963]185void ShadowMap::VisualizeFrustra()
[2911]186{
[2963]187        DrawPolyhedron(lightPoly, Vector3(1, 0, 1));
188        DrawPolyhedron(polyhedron, Vector3(0, 1, 0));
[2913]189}
[2911]190
[2913]191
[2944]192// z0 is the point that lies on the parallel plane to the near plane through e (A)
193//and on the near plane of the C frustum (the plane z = bZmax) and on the line x = e.x
194Vector3 ShadowMap::GetLightSpaceZ0(const Matrix4x4 &lightSpace,
195                                                                   const Vector3 &e,
196                                                                   const float maxZ,
197                                                                   const Vector3 &eyeDir) const
198{
199        // to calculate the parallel plane to the near plane through e we
200        // calculate the plane A with the three points
201        Plane3 planeA(e, eyeDir);
202
203        planeA.Transform(lightSpace);
204       
205        // get the parameters of A from the plane equation n dot d = 0
206        const float d = planeA.mD;
207        const Vector3 n = planeA.mNormal;
208       
209        // transform to light space
210        const Vector3 e_ls = lightSpace * e;
211
212        Vector3 z0;
213
214        z0.x = e_ls.x;
215        z0.y = (d - n.z * maxZ - n.x * e_ls.x) / n.y;
216        z0.z = maxZ;
217
218        return z0;
219        //return V3(e_ls.x(),(d-n.z()*b_lsZmax-n.x()*e_ls.x())/n.y(),b_lsZmax);
220}
221
222
223float ShadowMap::ComputeNOpt(const Matrix4x4 &lightSpace,
224                                                         const AxisAlignedBox3 &extremalPoints,
225                                                         const VertexArray &body) const
226{
227        const Vector3 nearPt = GetNearCameraPointE(body);
228        const Vector3 eyeDir = mCamera->GetDirection();
229
230        Matrix4x4 eyeView;
231        mCamera->GetModelViewMatrix(eyeView);
232
233        const Matrix4x4 invLightSpace = Invert(lightSpace);
234
235        const Vector3 z0_ls = GetLightSpaceZ0(lightSpace, nearPt, extremalPoints.Max().z, eyeDir);
236        const Vector3 z1_ls = Vector3(z0_ls.x, z0_ls.y, extremalPoints.Min().z);
237       
238        // transform back to world space
239        const Vector3 z0_ws = invLightSpace * z0_ls;
240        const Vector3 z1_ws = invLightSpace * z1_ls;
241
242        // transform to eye space
243        const Vector3 z0_es = eyeView * z0_ws;
244        const Vector3 z1_es = eyeView * z1_ws;
245
246        const float z0 = z0_es.z;
247        const float z1 = z1_es.z;
248
249        cout << "z0 ls: " << z0_ls << " z1 ls: " << z1_ls << endl;
250        cout << "z0: " << z0_es << " z1: " << z1_es << endl;
251
252        const float d = fabs(extremalPoints.Max()[2] - extremalPoints.Min()[2]);
253
254        const float n = d / (sqrt(z1 / z0) - 1.0f);
255
256        return n;
257}
258
259
[2920]260float ShadowMap::ComputeN(const AxisAlignedBox3 &extremalPoints) const
[2913]261{
[2944]262        const float nearPlane = mCamera->GetNear();
[2916]263       
[2920]264        const float d = fabs(extremalPoints.Max()[2] - extremalPoints.Min()[2]);
265       
[2916]266        const float dotProd = DotProd(mCamera->GetDirection(), mShadowCam->GetDirection());
267        const float sinGamma = sin(fabs(acos(dotProd)));
268
[2944]269        // test for values close to zero
270        if (sinGamma < 1e-6f) return 1e6f;
271       
[2954]272        const float scale = 2.0f;
273        return scale * (nearPlane + sqrt(nearPlane * (nearPlane + d * sinGamma))) /  sinGamma;
[2916]274}
275
276
[2924]277Matrix4x4 ShadowMap::CalcLispSMTransform(const Matrix4x4 &lightSpace,
[2920]278                                                                                 const AxisAlignedBox3 &extremalPoints,
[2924]279                                                                                 const VertexArray &body
[2920]280                                                                                 )
[2917]281{
[2928]282        AxisAlignedBox3 bounds_ls = GetExtremalPoints(lightSpace, body);
283
[2913]284        ///////////////
[2915]285        //-- We apply the lispsm algorithm in order to calculate an optimal light projection matrix
[2924]286        //-- first find the free parameter values n, and P (the projection center), and the projection depth
287
[2945]288        const float n = ComputeN(bounds_ls);
289        //const float n = ComputeNOpt(lightSpace, extremalPoints, body); cout << "n: " << n << endl;
[2924]290
[2944]291        if (n >= 1e6f) // light direction nearly parallel to view => switch to uniform
292                return IdentityMatrix();
293
[2924]294        const Vector3 nearPt = GetNearCameraPointE(body);
[2933]295       
[2915]296        //get the coordinates of the near camera point in light space
[2924]297        const Vector3 lsNear = lightSpace * nearPt;
[2915]298
[2939]299        // the start point has the x and y coordinate of e, the z coord of the near plane of the light volume
[2924]300        const Vector3 startPt = Vector3(lsNear.x, lsNear.y, bounds_ls.Max().z);
[2943]301       
[2915]302        // the new projection center
[2936]303        const Vector3 projCenter = startPt + Vector3::UNIT_Z() * n;
[2915]304
305        //construct a translation that moves to the projection center
306        const Matrix4x4 projectionCenter = TranslationMatrix(-projCenter);
307
[2916]308        // light space y size
[2933]309        const float d = fabs(bounds_ls.Max()[2] - bounds_ls.Min()[2]);
[2922]310
[2924]311        const float dy = fabs(bounds_ls.Max()[1] - bounds_ls.Min()[1]);
312        const float dx = fabs(bounds_ls.Max()[0] - bounds_ls.Min()[0]);
[2922]313
[2924]314       
[2915]315
[2928]316        //////////
[2924]317        //-- now apply these values to construct the perspective lispsm matrix
318
319        Matrix4x4 matLispSM;
320       
[2939]321        matLispSM = GetFrustum(-1.0, 1.0, -1.0, 1.0, n, n + d);
[2924]322
323        // translate to the projection center
[2920]324        matLispSM = projectionCenter * matLispSM;
[2915]325
326        // transform into OpenGL right handed system
[2920]327        Matrix4x4 refl = ScaleMatrix(1.0f, 1.0f, -1.0f);
328        matLispSM *= refl;
[2924]329       
[2920]330        return matLispSM;
[2915]331}
332
[2925]333#if 0
334Vector3 ShadowMap::GetNearCameraPointE(const VertexArray &pts) const
335{
336        float maxDist = -1e25f;
337        Vector3 nearest = Vector3::ZERO();
[2915]338
[2925]339        Matrix4x4 eyeView;
340        mCamera->GetModelViewMatrix(eyeView);
341
342        VertexArray newPts;
343        polyhedron->CollectVertices(newPts);
344       
345        //the LVS volume is always in front of the camera
346        VertexArray::const_iterator it, it_end = pts.end();     
347
348        for (it = pts.begin(); it != it_end; ++ it)
349        {
350                Vector3 pt = *it;
351                Vector3 ptE = eyeView * pt;
[2943]352               
[2925]353                if (ptE.z > 0) cerr <<"should not happen " << ptE.z << endl;
354                else
355                if (ptE.z > maxDist)
356                {
357                        cout << " d " << ptE.z;
358       
359                        maxDist = ptE.z;
360                        nearest = pt;
361                }
362        }
363
[2933]364        //      return Invert(eyeView) * nearest;
[2925]365        return nearest;
366}
367
368#else
369
[2920]370Vector3 ShadowMap::GetNearCameraPointE(const VertexArray &pts) const
[2919]371{
[2925]372        VertexArray newPts;
373        polyhedron->CollectVertices(newPts);
374
[2922]375        Vector3 nearest = Vector3::ZERO();
376        float minDist = 1e25f;
[2920]377
[2924]378        const Vector3 camPos = mCamera->GetPosition();
[2920]379
[2925]380        VertexArray::const_iterator it, it_end = newPts.end();
[2920]381
[2925]382        for (it = newPts.begin(); it != it_end; ++ it)
[2920]383        {
384                Vector3 pt = *it;
385
386                const float dist = SqrDistance(pt, camPos);
387
388                if (dist < minDist)
389                {
390                        minDist = dist;
391                        nearest = pt;
392                }
393        }
394
395        return nearest;
396}
397
[2925]398#endif
[2920]399
[2933]400Vector3 ShadowMap::GetProjViewDir(const Matrix4x4 &lightSpace,
401                                                                  const VertexArray &pts) const
[2920]402{
[2919]403        //get the point in the LVS volume that is nearest to the camera
[2920]404        const Vector3 e = GetNearCameraPointE(pts);
405
[2919]406        //construct edge to transform into light-space
[2920]407        const Vector3 b = e + mCamera->GetDirection();
[2919]408        //transform to light-space
[2920]409        const Vector3 e_lp = lightSpace * e;
410        const Vector3 b_lp = lightSpace * b;
411
412        Vector3 projDir(b_lp - e_lp);
413
[2919]414        //project the view direction into the shadow map plane
[2932]415        projDir.y = .0f;
[2920]416
417        return Normalize(projDir);
[2919]418}
419
420
[2915]421bool ShadowMap::CalcLightProjection(Matrix4x4 &lightProj)
422{
423        ///////////////////
424        //-- First step: calc frustum clipped by scene box
425
[2922]426        DEL_PTR(polyhedron);
[2915]427        polyhedron = CalcClippedFrustum(mSceneBox);
428
429        if (!polyhedron) return false; // something is wrong
430
431        // include the part of the light volume that "sees" the frustum
432        // we only require frustum vertices
433
434        VertexArray frustumPoints;
[2939]435        IncludeLightVolume(*polyhedron, frustumPoints, mLight->GetDirection(), mSceneBox);
[2915]436
437
438        ///////////////
439        //-- transform points from world view to light view and calculate extremal points
440
441        Matrix4x4 lightView;
442        mShadowCam->GetModelViewMatrix(lightView);
443
[2920]444        const AxisAlignedBox3 extremalPoints = GetExtremalPoints(lightView, frustumPoints);
[2913]445
[2920]446        // we use directional lights, so the projection can be set to identity
447        lightProj = IdentityMatrix();
[2913]448
[2922]449        // switch coordinate system to that used in the lispsm algorithm for calculations
450        Matrix4x4 transform2LispSM = ZeroMatrix();
451
452        transform2LispSM.x[0][0] =  1.0f;
[2934]453        transform2LispSM.x[1][2] =  -1.0f; // y => -z
[2924]454        transform2LispSM.x[2][1] =  1.0f; // z => y
[2922]455        transform2LispSM.x[3][3] =  1.0f;
456
[2936]457
[2922]458        //switch to the lightspace used in the article
[2936]459        lightProj *= transform2LispSM;
[2922]460
[2924]461        const Vector3 projViewDir = GetProjViewDir(lightView * lightProj, frustumPoints);
[2916]462
[2952]463        //do DirectionalLight Space Perspective shadow mapping
[2922]464        //rotate the lightspace so that the projected light view always points upwards
465        //calculate a frame matrix that uses the projViewDir[lightspace] as up vector
[2917]466        //look(from position, into the direction of the projected direction, with unchanged up-vector)
[2938]467        //const Matrix4x4 frame = MyLookAt2(Vector3::ZERO(), projViewDir, Vector3::UNIT_Y());
[2944]468        const Matrix4x4 frame = LookAt(Vector3::ZERO(), projViewDir, Vector3::UNIT_Y());
[2917]469
[2936]470        lightProj *= frame;
[2924]471
[2917]472        const Matrix4x4 matLispSM =
[2920]473                CalcLispSMTransform(lightView * lightProj, extremalPoints, frustumPoints);
[2917]474
[2936]475        lightProj *= matLispSM;
[2917]476
[2922]477        // change back to GL coordinate system
478        Matrix4x4 transformToGL = ZeroMatrix();
479       
[2940]480        transformToGL.x[0][0] =   1.0f;
481        transformToGL.x[1][2] =   1.0f; // z => y
[2934]482        transformToGL.x[2][1] =  -1.0f; // y => -z
[2940]483        transformToGL.x[3][3] =   1.0f;
[2922]484
[2936]485        lightProj *= transformToGL;
[2922]486
[2920]487        AxisAlignedBox3 lightPts = GetExtremalPoints(lightView * lightProj, frustumPoints);
488
[2917]489        // focus projection matrix on the extremal points => scale to unit cube
[2922]490        Matrix4x4 scaleTranslate = GetFittingProjectionMatrix(lightPts);
[2917]491
[2939]492        lightProj = lightProj * scaleTranslate;
493
494        Matrix4x4 mymat = lightView * lightProj;
495
496        AxisAlignedBox3 lightPtsNew = GetExtremalPoints(mymat, frustumPoints);
497
[2920]498        // we have to flip the signs in order to tranform to opengl right handed system
499        Matrix4x4 refl = ScaleMatrix(1, 1, -1);
500        lightProj *= refl;
[2916]501       
[2913]502        return true;
[2911]503}
504
505
[2913]506Polyhedron *ShadowMap::CalcClippedFrustum(const AxisAlignedBox3 &box) const
507{
[2931]508        Polyhedron *p = mCamera->ComputeFrustum();
509       
510        Polyhedron *clippedPolyhedron = box.CalcIntersection(*p);
[2913]511
[2931]512        DEL_PTR(p);
[2913]513       
[2931]514        return clippedPolyhedron;
515}
[2913]516
517
[2931]518//calculates the up vector for the light coordinate frame
519static Vector3 CalcUpVec(const Vector3 viewDir, const Vector3 lightDir)
520{
521        //we do what gluLookAt does...
522        //left is the normalized vector perpendicular to lightDir and viewDir
523        //this means left is the normalvector of the yz-plane from the paper
524        Vector3 left = CrossProd(lightDir, viewDir);
[2913]525       
[2931]526        //we now can calculate the rotated(in the yz-plane) viewDir vector
527        //and use it as up vector in further transformations
528        Vector3 up = CrossProd(left, lightDir);
[2913]529
[2931]530        return Normalize(up);
[2913]531}
532
533
[2932]534void ShadowMap::GetTextureMatrix(Matrix4x4 &m) const
535{
536        m = mTextureMatrix;
537}
538
539 
540unsigned int ShadowMap::GetDepthTexture() const
541{
542        return mFbo->GetDepthTex();
543}
544
545unsigned int ShadowMap::GetShadowColorTexture() const
546{
547        return mFbo->GetColorBuffer(0)->GetTexture();
548       
549}
550
551
552void ShadowMap::IncludeLightVolume(const Polyhedron &polyhedron,
553                                                                   VertexArray &frustumPoints,
554                                                                   const Vector3 lightDir,
555                                                                   const AxisAlignedBox3 &sceneBox
556                                                                   )
557{
558        // we don't need closed form anymore => just store vertices
559        VertexArray vertices;
560        polyhedron.CollectVertices(vertices);
561
562        // we 'look' at each point and calculate intersections of rays with scene bounding box
563        VertexArray::const_iterator it, it_end = vertices.end();
564
565        for (it = vertices.begin(); it != it_end; ++ it)
566        {
567                Vector3 v  = *it;
568
569                frustumPoints.push_back(v);
570               
[2939]571                // hack: start at point which is guaranteed to be outside of box
[2932]572                v -= Magnitude(mSceneBox.Diagonal()) * lightDir;
573
574                SimpleRay ray(v, lightDir);
575
576                float tNear, tFar;
577
578                if (sceneBox.Intersects(ray, tNear, tFar))
579                {
580                        Vector3 newpt = ray.Extrap(tNear);
581                        frustumPoints.push_back(newpt);                 
582                }
583        }
584}
585
586
[2911]587void ShadowMap::ComputeShadowMap(RenderTraverser *renderer, const Matrix4x4 &projView)
588{
[2891]589        mFbo->Bind();
[2892]590       
[2891]591        glDrawBuffers(1, mrt);
592
593        glPushAttrib(GL_VIEWPORT_BIT);
594        glViewport(0, 0, mSize, mSize);
595
596        glDisable(GL_LIGHTING);
597        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
598
599        glShadeModel(GL_FLAT);
600
601
[2942]602        /////////////
603        //-- render scene into shadow map
[2894]604
[2942]605        _Render(renderer);
[2911]606
[2939]607
[2913]608        //////////////
609        //-- compute texture matrix
[2925]610
[2894]611        static Matrix4x4 biasMatrix(0.5f, 0.0f, 0.0f, 0.5f,
612                                                                0.0f, 0.5f, 0.0f, 0.5f,
613                                                                0.0f, 0.0f, 0.5f, 0.5f,
[2911]614                                                                0.0f, 0.0f, 0.0f, 1.0f);
[2894]615
[2911]616        mTextureMatrix = mLightProjView * biasMatrix;
[2894]617
[2891]618        glPopAttrib();
[2928]619       
[2943]620        glShadeModel(GL_SMOOTH);
[2928]621        glEnable(GL_LIGHTING);
622        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
623
[2913]624#if 0
[2911]625        float *data = new float[mSize * mSize];
[2891]626
627        GrabDepthBuffer(data, mFbo->GetDepthTex());
628        ExportDepthBuffer(data, mSize);
629
[2892]630        delete [] data;
[2911]631       
[2892]632        PrintGLerror("shadow map");
[2913]633#endif
[2942]634       
[2891]635        FrameBufferObject::Release();
636}
637
638
[2931]639void ShadowMap::RenderShadowView(RenderTraverser *renderer, const Matrix4x4 &projView)
640{
[2942]641        glEnable(GL_LIGHTING);
[2943]642       
[2942]643        _Render(renderer);
644       
[2943]645        /*glDisable(GL_LIGHTING);
646        glDisable(GL_DEPTH_TEST);
647
648        //glLineWidth(2);
649        Polyhedron *hpoly = CreatePolyhedron(projView, mSceneBox);
650        DrawPoly(hpoly, Vector3(1, 1, 1));
651
652        DEL_PTR(hpoly);
653
654        glEnable(GL_LIGHTING);
655        glEnable(GL_DEPTH_TEST);*/
656
[2942]657        glDisable(GL_POLYGON_OFFSET_FILL);
658}
659
660
661void ShadowMap::_Render(RenderTraverser *renderer)
662{
[2939]663        const Vector3 dir = mLight->GetDirection();
[2931]664
665        mShadowCam->SetDirection(dir);
666
667        // set position so that we can see the whole scene
668        Vector3 pos = mSceneBox.Center();
669        pos -= dir * Magnitude(mSceneBox.Diagonal() * 0.5f);
670
[2932]671        mShadowCam->SetPosition(mCamera->GetPosition());
672
673        Vector3 upVec = CalcUpVec(mCamera->GetDirection(), dir);
[2944]674        Matrix4x4 lightView = LookAt(mShadowCam->GetPosition(), dir, upVec);
[2932]675
676        mShadowCam->mViewOrientation = lightView;
677
[2931]678        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
679
[2944]680        glPolygonOffset(5.0f, 100.0f);
[2931]681        glEnable(GL_POLYGON_OFFSET_FILL);
[2932]682       
683        Matrix4x4 lightProj;
[2931]684        CalcLightProjection(lightProj);
685
686        glMatrixMode(GL_PROJECTION);
687        glPushMatrix();
688        glLoadMatrixf((float *)lightProj.x);
689
690        mLightProjView = lightView * lightProj;
[2932]691
[2931]692        DEL_PTR(lightPoly);
693        lightPoly = CreatePolyhedron(mLightProjView, mSceneBox);
694
695        glMatrixMode(GL_MODELVIEW);
696        glPushMatrix();
[2951]697       
[2932]698        mShadowCam->SetupCameraView();
[2931]699
[2942]700       
[2931]701        /////////////
702        //-- render scene into shadow map
703
704        renderer->RenderScene();
705
[2943]706
[2931]707        glMatrixMode(GL_PROJECTION);
708        glPopMatrix();
709
[2951]710        glMatrixMode(GL_MODELVIEW);
711        glPopMatrix();
712
[2931]713       
[2942]714        glDisable(GL_POLYGON_OFFSET_FILL);
[2931]715}
[2891]716} // namespace
Note: See TracBrowser for help on using the repository browser.