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

Revision 2891, 9.9 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)
96                cgDestroyProgram(sCgShadowProgram);
97
98        DEL_PTR(mFbo);
99}
100
101
102void ShadowMapping::Init(CGcontext context)
103{/*
104        sCgShadowProgram =
105                cgCreateProgramFromFile(context,
106                                                                CG_SOURCE,
107                                                                "src/shaders/shadow.cg",
108                                                                RenderState::sCgFragmentProfile,
109                                                                "main",
110                                                                NULL);
111
112        if (sCgShadowProgram != NULL)
113        {
114                cgGLLoadProgram(sCgShadowProgram);
115                sShadowParam = cgGetNamedParameter(sCgShadowProgram, "shadowMap");
116        }
117        else
118                cerr << "shadow program failed to load" << endl;
119*/
120        PrintGLerror("init");
121}
122
123
124void ShadowMapping::ComputeShadowMap(Light *light, RenderTraverser *traverser)
125{
126        mLight = light;
127
128        const float xlen = Magnitude(mSceneBox.Diagonal() * 0.5f);
129        const float ylen = Magnitude(mSceneBox.Diagonal() * 0.5f);
130       
131        mShadowCam->SetDirection(light->GetDirection());
132       
133        // set position so that we can see the whole scene
134        Vector3 pos = mSceneBox.Center();
135        pos.z = mSceneBox.Max().z;
136        //mShadowCam->SetPosition(pos - Magnitude(mSceneBox.Diagonal() * light->GetDirection()));
137        mShadowCam->SetPosition(pos);
138
139        mFbo->Bind();
140
141        glDrawBuffers(1, mrt);
142
143        glPushAttrib(GL_VIEWPORT_BIT);
144        glViewport(0, 0, mSize, mSize);
145
146        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
147
148        glDisable(GL_LIGHTING);
149        glDisable(GL_TEXTURE_2D);
150        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
151
152        glPolygonOffset(1.0f, 4000.0f);
153        //glEnable(GL_POLYGON_OFFSET_FILL);
154
155        glShadeModel(GL_FLAT);
156        glEnable(GL_DEPTH_TEST);
157
158        glMatrixMode(GL_PROJECTION);
159        glPushMatrix();
160
161        glOrtho(+xlen, -xlen, ylen, -ylen, 0.0f, Magnitude(mSceneBox.Diagonal()));
162
163        glMatrixMode(GL_MODELVIEW);
164        glPushMatrix();
165
166        mShadowCam->SetupCameraView();
167
168        mShadowCam->GetModelViewMatrix(mShadowMatrix);
169
170        traverser->RenderScene();
171       
172        glDisable(GL_POLYGON_OFFSET_FILL);
173
174        glPopMatrix();
175
176        glMatrixMode(GL_PROJECTION);
177        glPopMatrix();
178
179        glPopAttrib();
180       
181        /*float *data = new float[mSize * mSize];
182
183        GrabDepthBuffer(data, mFbo->GetDepthTex());
184        ExportDepthBuffer(data, mSize);
185
186        delete [] data;*/
187
188        FrameBufferObject::Release();
189}
190
191/*
192void ShadowMapping::Render(RenderTraverser *traverser, Camera *cam)
193{
194        Matrix4x4 cam_proj;
195        Matrix4x4 cam_inverse_modelview;
196
197        const float bias[16] =
198        {0.5f, 0.0f, 0.0f, 0.0f,
199        0.0f, 0.5f, 0.0f, 0.0f,
200        0.0f, 0.0f, 0.5f, 0.0f,
201        0.5f, 0.5f, 0.5f, 1.0f  };
202
203
204        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
205
206        // update the camera, so that the user can have a free look
207        glMatrixMode(GL_MODELVIEW);
208        glLoadIdentity();
209       
210        glMatrixMode(GL_PROJECTION);
211        glLoadIdentity();
212       
213        cam->SetupCameraView();
214
215        // store the inverse of the resulting modelview matrix for the shadow computation
216        glGetFloatv(GL_MODELVIEW_MATRIX, (float *)cam_inverse_modelview.x);
217        cam_inverse_modelview.Invert();
218
219        // bind shadow map
220        glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mFbo->GetDepthTex());
221
222        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
223        //glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_MODE, GL_NONE);
224
225        PrintGLerror("texture");
226
227        //float light_m[16];
228       
229        // compute a matrix that transforms from camera eye space to light clip space
230        // and pass it to the shader through the OpenGL texture matrices, since we
231        // don't use them now
232        glEnable(GL_TEXTURE_2D);
233        glMatrixMode(GL_TEXTURE);
234
235        glLoadMatrixf(bias);
236        glMultMatrixf((float *)mShadowMatrix.x);
237       
238        // multiply the light's (bias * crop * proj * modelview) by the inverse camera modelview
239        // so that we can transform a pixel as seen from the camera
240        glMultMatrixf((float *)cam_inverse_modelview.x);
241       
242               
243        cgGLEnableProfile(RenderState::sCgFragmentProfile);
244        cgGLBindProgram(sCgShadowProgram);
245       
246        cgGLSetTextureParameter(sShadowParam, mFbo->GetDepthTex());
247        cgGLEnableTextureParameter(sShadowParam);
248       
249        // finally, draw the scene
250        traverser->RenderScene();
251
252        cgGLDisableTextureParameter(sShadowParam);
253
254        PrintGLerror("shadow");
255}
256*/
257
258
259//Called to draw scene
260void ShadowMapping::Render(RenderTraverser *traverser, Camera *cam)
261{
262        Matrix4x4 cam_inverse_modelview;
263
264        //Calculate texture matrix for projection
265        //This matrix takes us from eye space to the light's clip space
266        //It is postmultiplied by the inverse of the current view matrix when specifying texgen
267        static Matrix4x4 biasMatrix(0.5f, 0.0f, 0.0f, 0.0f,
268                                                                0.0f, 0.5f, 0.0f, 0.0f,
269                                                                0.0f, 0.0f, 0.5f, 0.0f,
270                                                                0.5f, 0.5f, 0.5f, 1.0f); //bias from [-1, 1] to [0, 1]
271
272        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
273
274        // update the camera, so that the user can have a free look
275        glMatrixMode(GL_MODELVIEW);
276        glLoadIdentity();
277       
278        glMatrixMode(GL_PROJECTION);
279        glLoadIdentity();
280       
281        cam->SetupCameraView();
282
283        // store the inverse of the resulting modelview matrix for the shadow computation
284        glGetFloatv(GL_MODELVIEW_MATRIX, (float *)cam_inverse_modelview.x);
285        cam_inverse_modelview.Invert();
286
287        // bind shadow map
288        glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mFbo->GetDepthTex());
289
290        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
291        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
292
293        PrintGLerror("texture");
294       
295        // compute a matrix that transforms from camera eye space to light clip space
296        // and pass it to the shader through the OpenGL texture matrices, since we
297        // don't use them now
298        glEnable(GL_TEXTURE_2D);
299        glMatrixMode(GL_TEXTURE);
300
301        glLoadMatrixf((float *)biasMatrix.x);
302        glMultMatrixf((float *)mShadowMatrix.x);
303       
304        // multiply the light's (bias * crop * proj * modelview) by the inverse camera modelview
305        // so that we can transform a pixel as seen from the camera
306        glMultMatrixf((float *)cam_inverse_modelview.x);
307
308        RgbaColor white(1, 1, 1, 0);
309        RgbaColor dark(0.2, 0.2, 0.2, 0);
310
311        //Use dim light to represent shadowed areas
312        glLightfv(GL_LIGHT1, GL_POSITION, mLight->GetDirection());
313        glLightfv(GL_LIGHT1, GL_AMBIENT, (float *)&dark.r);
314        glLightfv(GL_LIGHT1, GL_DIFFUSE, (float *)&white.r);
315        //glLightfv(GL_LIGHT1, GL_SPECULAR, black);
316        glEnable(GL_LIGHT1);
317        glEnable(GL_LIGHTING);
318
319       
320        // finally, draw the scene
321        traverser->RenderScene();
322
323       
324
325        //3rd pass
326        //Draw with bright light
327        glLightfv(GL_LIGHT1, GL_DIFFUSE, (float *)&white.r);
328        glLightfv(GL_LIGHT1, GL_SPECULAR, (float *)&white.r);
329
330        Matrix4x4 textureMatrix;// = biasMatrix * mLightProjectionMatrix * mLightViewMatrix;
331
332        //Set up texture coordinate generation.
333        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
334        //glTexGenfv(GL_S, GL_EYE_PLANE, textureMatrix.GetRow(0));
335        glEnable(GL_TEXTURE_GEN_S);
336
337        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
338        //glTexGenfv(GL_T, GL_EYE_PLANE, textureMatrix.GetRow(1));
339        glEnable(GL_TEXTURE_GEN_T);
340
341        glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
342        //glTexGenfv(GL_R, GL_EYE_PLANE, textureMatrix.GetRow(2));
343        glEnable(GL_TEXTURE_GEN_R);
344
345        glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
346        //glTexGenfv(GL_Q, GL_EYE_PLANE, textureMatrix.GetRow(3));
347        glEnable(GL_TEXTURE_GEN_Q);
348
349        //Bind & enable shadow map texture
350        glBindTexture(GL_TEXTURE_2D, mFbo->GetDepthTex());
351        glEnable(GL_TEXTURE_2D);
352
353        //Enable shadow comparison
354        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
355
356        //Shadow comparison should be true (ie not in shadow) if r<=texture
357        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
358
359        //Shadow comparison should generate an INTENSITY result
360        glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);
361
362        //Set alpha test to discard false comparisons
363        glAlphaFunc(GL_GEQUAL, 0.99f);
364        glEnable(GL_ALPHA_TEST);
365
366        traverser->RenderScene();
367
368        //Disable textures and texgen
369        glDisable(GL_TEXTURE_2D);
370
371        glDisable(GL_TEXTURE_GEN_S);
372        glDisable(GL_TEXTURE_GEN_T);
373        glDisable(GL_TEXTURE_GEN_R);
374        glDisable(GL_TEXTURE_GEN_Q);
375
376        //Restore other states
377        glDisable(GL_LIGHTING);
378        glDisable(GL_ALPHA_TEST);
379}
380
381
382} // namespace
Note: See TracBrowser for help on using the repository browser.