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

Revision 2892, 10.2 KB checked in by mattausch, 16 years ago (diff)
Line 
1#include "ShadowMapping.h"
2#include "FrameBufferObject.h"
3#include "RenderState.h"
4#include "RenderTraverser.h"
5#include "Light.h"
6#include <IL/il.h>
7#include <assert.h>
8
9using namespace std;
10
11
12namespace CHCDemoEngine
13{
14
15static GLenum mrt[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT};
16
17static void PrintGLerror(char *msg)
18{
19        GLenum errCode;
20        const GLubyte *errStr;
21       
22        if ((errCode = glGetError()) != GL_NO_ERROR)
23        {
24                errStr = gluErrorString(errCode);
25                fprintf(stderr,"OpenGL ERROR: %s: %s\n", errStr, msg);
26        }
27}
28
29
30
31static CGprogram sCgShadowProgram;
32static CGparameter sShadowParam;
33
34
35static void GrabDepthBuffer(float *data, GLuint depthTexture)
36{
37        glEnable(GL_TEXTURE_2D);
38        glBindTexture(GL_TEXTURE_2D, depthTexture);
39
40        glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, data);
41
42        glBindTexture(GL_TEXTURE_2D, 0);
43        glDisable(GL_TEXTURE_2D);
44}
45
46
47static void ExportDepthBuffer(float *data, int size)
48{
49        ilInit();
50        assert(ilGetError() == IL_NO_ERROR);
51
52        ILstring filename = ILstring("shadow.tga");
53        ilRegisterType(IL_FLOAT);
54
55        const int depth = 1;
56        const int bpp = 1;
57
58        if (!ilTexImage(size, size, depth, bpp, IL_LUMINANCE, IL_FLOAT, data))
59        {
60                cerr << "IL error " << ilGetError() << endl;
61       
62                ilShutDown();
63                assert(ilGetError() == IL_NO_ERROR);
64
65                return;
66        }
67
68        if (!ilSaveImage(filename))
69        {
70                cerr << "TGA write error " << ilGetError() << endl;
71        }
72
73        ilShutDown();
74        assert(ilGetError() == IL_NO_ERROR);
75
76        cout << "exported depth buffer" << endl;
77}
78
79
80
81ShadowMapping::ShadowMapping(const AxisAlignedBox3 &sceneBox, int size):
82mSceneBox(sceneBox), mSize(size)
83{
84        mFbo = new FrameBufferObject(size, size, FrameBufferObject::DEPTH_32, true);
85        // the diffuse color buffer
86        mFbo->AddColorBuffer(ColorBufferObject::BUFFER_UBYTE, ColorBufferObject::WRAP_CLAMP_TO_EDGE, ColorBufferObject::FILTER_LINEAR, false);
87
88        mShadowCam = new Camera(mSceneBox.Size().x * 0.5f, mSceneBox.Size().y * 0.5f);
89        mShadowCam->SetOrtho(true);
90}
91
92
93ShadowMapping::~ShadowMapping()
94{
95        //if (sCgShadowProgram) cgDestroyProgram(sCgShadowProgram);
96        DEL_PTR(mFbo);
97}
98
99
100void ShadowMapping::Init(CGcontext context)
101{/*
102        sCgShadowProgram =
103                cgCreateProgramFromFile(context,
104                                                                CG_SOURCE,
105                                                                "src/shaders/shadow.cg",
106                                                                RenderState::sCgFragmentProfile,
107                                                                "main",
108                                                                NULL);
109
110        if (sCgShadowProgram != NULL)
111        {
112                cgGLLoadProgram(sCgShadowProgram);
113                sShadowParam = cgGetNamedParameter(sCgShadowProgram, "shadowMap");
114        }
115        else
116                cerr << "shadow program failed to load" << endl;
117*/
118        PrintGLerror("init");
119}
120
121
122void ShadowMapping::ComputeShadowMap(Light *light, RenderTraverser *traverser)
123{
124        mLight = light;
125
126        const float xlen = Magnitude(mSceneBox.Diagonal());// * 0.5f);
127        const float ylen = Magnitude(mSceneBox.Diagonal());// * 0.5f);
128       
129        mShadowCam->SetDirection(light->GetDirection());
130       
131        // set position so that we can see the whole scene
132        Vector3 pos = mSceneBox.Center();
133        pos.z = mSceneBox.Max().z;
134        //mShadowCam->SetPosition(pos - Magnitude(mSceneBox.Diagonal() * light->GetDirection()));
135        mShadowCam->SetPosition(pos);
136
137        mFbo->Bind();
138       
139        glDrawBuffers(1, mrt);
140
141        glPushAttrib(GL_VIEWPORT_BIT);
142        glViewport(0, 0, mSize, mSize);
143
144        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
145
146        glDisable(GL_LIGHTING);
147        glDisable(GL_TEXTURE_2D);
148        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
149
150        glPolygonOffset(1.0f, 40.0f);
151        glEnable(GL_POLYGON_OFFSET_FILL);
152
153        glShadeModel(GL_FLAT);
154        glEnable(GL_DEPTH_TEST);
155
156        glMatrixMode(GL_PROJECTION);
157        glPushMatrix();
158        glLoadIdentity();
159       
160        glOrtho(+xlen, -xlen, +ylen, -ylen, 0.0f, 100);//Magnitude(mSceneBox.Diagonal()));
161       
162
163        glMatrixMode(GL_MODELVIEW);
164        glPushMatrix();
165
166        glLoadIdentity();
167
168
169        mShadowCam->SetupCameraView();
170        mShadowCam->GetModelViewMatrix(mLightViewMatrix);
171
172        mShadowCam->GetProjectionMatrix(mLightProjectionMatrix);
173        //glGetFloatv(GL_MODELVIEW_MATRIX, (float *)mLightProjectionMatrix.x);
174
175        traverser->RenderScene();
176       
177        glDisable(GL_POLYGON_OFFSET_FILL);
178        glMatrixMode(GL_MODELVIEW);
179        glPopMatrix();
180
181        glMatrixMode(GL_PROJECTION);
182        glPopMatrix();
183
184        glPopAttrib();
185       
186        /*float *data = new float[mSize * mSize];
187
188        GrabDepthBuffer(data, mFbo->GetDepthTex());
189        ExportDepthBuffer(data, mSize);
190
191        delete [] data;
192*/
193        PrintGLerror("shadow map");
194
195        FrameBufferObject::Release();
196}
197
198/*
199void ShadowMapping::Render(RenderTraverser *traverser, Camera *cam)
200{
201        Matrix4x4 cam_proj;
202        Matrix4x4 cam_inverse_modelview;
203
204        const float bias[16] =
205        {0.5f, 0.0f, 0.0f, 0.0f,
206        0.0f, 0.5f, 0.0f, 0.0f,
207        0.0f, 0.0f, 0.5f, 0.0f,
208        0.5f, 0.5f, 0.5f, 1.0f  };
209
210
211        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
212
213        // update the camera, so that the user can have a free look
214        glMatrixMode(GL_MODELVIEW);
215        glLoadIdentity();
216       
217        glMatrixMode(GL_PROJECTION);
218        glLoadIdentity();
219       
220        cam->SetupCameraView();
221
222        // store the inverse of the resulting modelview matrix for the shadow computation
223        glGetFloatv(GL_MODELVIEW_MATRIX, (float *)cam_inverse_modelview.x);
224        cam_inverse_modelview.Invert();
225
226        // bind shadow map
227        glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mFbo->GetDepthTex());
228
229        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
230        //glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_MODE, GL_NONE);
231
232        PrintGLerror("texture");
233
234        //float light_m[16];
235       
236        // compute a matrix that transforms from camera eye space to light clip space
237        // and pass it to the shader through the OpenGL texture matrices, since we
238        // don't use them now
239        glEnable(GL_TEXTURE_2D);
240        glMatrixMode(GL_TEXTURE);
241
242        glLoadMatrixf(bias);
243        glMultMatrixf((float *)mShadowMatrix.x);
244       
245        // multiply the light's (bias * crop * proj * modelview) by the inverse camera modelview
246        // so that we can transform a pixel as seen from the camera
247        glMultMatrixf((float *)cam_inverse_modelview.x);
248       
249               
250        cgGLEnableProfile(RenderState::sCgFragmentProfile);
251        cgGLBindProgram(sCgShadowProgram);
252       
253        cgGLSetTextureParameter(sShadowParam, mFbo->GetDepthTex());
254        cgGLEnableTextureParameter(sShadowParam);
255       
256        // finally, draw the scene
257        traverser->RenderScene();
258
259        cgGLDisableTextureParameter(sShadowParam);
260
261        PrintGLerror("shadow");
262}
263*/
264
265
266//Called to draw scene
267void ShadowMapping::Render(RenderTraverser *traverser, Camera *cam)
268{
269        Matrix4x4 cam_inverse_modelview;
270
271        //Calculate texture matrix for projection
272        //This matrix takes us from eye space to the light's clip space
273        //It is postmultiplied by the inverse of the current view matrix when specifying texgen
274        static Matrix4x4 biasMatrix(0.5f, 0.0f, 0.0f, 0.0f,
275                                                                0.0f, 0.5f, 0.0f, 0.0f,
276                                                                0.0f, 0.0f, 0.5f, 0.0f,
277                                                                0.5f, 0.5f, 0.5f, 1.0f); //bias from [-1, 1] to [0, 1]
278
279        /*glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
280
281        // update the camera, so that the user can have a free look
282        glMatrixMode(GL_MODELVIEW);
283        glLoadIdentity();
284       
285        glMatrixMode(GL_PROJECTION);
286        glLoadIdentity();
287       
288        cam->SetupCameraView();
289*/
290        // store the inverse of the resulting modelview matrix for the shadow computation
291        glGetFloatv(GL_MODELVIEW_MATRIX, (float *)cam_inverse_modelview.x);
292        cam_inverse_modelview.Invert();
293
294        // bind shadow map
295        glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mFbo->GetDepthTex());
296       
297        // compute a matrix that transforms from camera eye space to light clip space
298        // and pass it to the shader through the OpenGL texture matrices, since we
299        // don't use them now
300        glEnable(GL_TEXTURE_2D);
301        glMatrixMode(GL_TEXTURE);
302
303        glLoadMatrixf((float *)biasMatrix.x);
304        glMultMatrixf((float *)mLightViewMatrix.x);
305       
306        // multiply the light's (bias * crop * proj * modelview) by the inverse camera modelview
307        // so that we can transform a pixel as seen from the camera
308        glMultMatrixf((float *)cam_inverse_modelview.x);
309
310        RgbaColor white(1, 1, 1, 0);
311        RgbaColor dark(0.2, 0.2, 0.2, 0);
312
313        glDisable(GL_LIGHTING);
314
315        /*glDisable(GL_LIGHT0);
316        glDisable(GL_LIGHT1);
317
318        //Use dim light to represent shadowed areas
319        glLightfv(GL_LIGHT1, GL_POSITION, mLight->GetDirection());
320        glLightfv(GL_LIGHT1, GL_AMBIENT, (float *)&dark.r);
321        glLightfv(GL_LIGHT1, GL_DIFFUSE, (float *)&white.r);
322        //glLightfv(GL_LIGHT1, GL_SPECULAR, black);
323        glEnable(GL_LIGHT1);
324        glEnable(GL_LIGHTING);*/
325
326        PrintGLerror("firstpass");
327
328        // finally, draw the scene
329        traverser->RenderScene();
330
331
332        glEnable(GL_LIGHTING);
333
334
335        //3rd pass
336        //Draw with bright light
337        //glLightfv(GL_LIGHT1, GL_DIFFUSE, (float *)&white.r);
338        //glLightfv(GL_LIGHT1, GL_SPECULAR, (float *)&white.r);
339
340        Matrix4x4 textureMatrix = biasMatrix * mLightProjectionMatrix * mLightViewMatrix;
341
342        Matrix4x4 texMatT = Transpose(textureMatrix);
343
344        //Set up texture coordinate generation.
345        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
346        glTexGenfv(GL_S, GL_EYE_PLANE, texMatT.x[0]);
347        glEnable(GL_TEXTURE_GEN_S);
348
349        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
350        glTexGenfv(GL_T, GL_EYE_PLANE, texMatT.x[1]);
351        glEnable(GL_TEXTURE_GEN_T);
352
353        glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
354        glTexGenfv(GL_R, GL_EYE_PLANE, texMatT.x[2]);
355        glEnable(GL_TEXTURE_GEN_R);
356
357        glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
358        glTexGenfv(GL_Q, GL_EYE_PLANE, texMatT.x[3]);
359        glEnable(GL_TEXTURE_GEN_Q);
360
361        //Bind & enable shadow map texture
362        glBindTexture(GL_TEXTURE_2D, mFbo->GetDepthTex());
363        glEnable(GL_TEXTURE_2D);
364
365        //Enable shadow comparison
366        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
367
368        //Shadow comparison should be true (ie not in shadow) if r<=texture
369        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
370
371        //Shadow comparison should generate an INTENSITY result
372        glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);
373
374        //Set alpha test to discard false comparisons
375        glAlphaFunc(GL_GEQUAL, 0.99f);
376        glEnable(GL_ALPHA_TEST);
377
378        PrintGLerror("texture");
379
380        traverser->RenderScene();
381
382        //Disable textures and texgen
383        glDisable(GL_TEXTURE_2D);
384
385        glDisable(GL_TEXTURE_GEN_S);
386        glDisable(GL_TEXTURE_GEN_T);
387        glDisable(GL_TEXTURE_GEN_R);
388        glDisable(GL_TEXTURE_GEN_Q);
389
390        //Restore other states
391        glDisable(GL_LIGHTING);
392        glDisable(GL_ALPHA_TEST);
393}
394
395
396} // namespace
Note: See TracBrowser for help on using the repository browser.