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

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

working on dynamic stuff again

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