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

Revision 2893, 10.2 KB checked in by mattausch, 16 years ago (diff)

shadowing partly working

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
134        pos -= light->GetDirection() * Magnitude(mSceneBox.Diagonal() * 0.5f);
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, 2000.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        glLoadIdentity();
161       
162        glOrtho(+xlen, -xlen, +ylen, -ylen, 0.0f, Magnitude(mSceneBox.Diagonal()));
163       
164
165        glMatrixMode(GL_MODELVIEW);
166        glPushMatrix();
167
168        glLoadIdentity();
169
170
171        mShadowCam->SetupCameraView();
172        mShadowCam->GetModelViewMatrix(mLightViewMatrix);
173
174        mShadowCam->GetProjectionMatrix(mLightProjectionMatrix);
175        //glGetFloatv(GL_MODELVIEW_MATRIX, (float *)mLightProjectionMatrix.x);
176
177        traverser->RenderScene();
178       
179        glDisable(GL_POLYGON_OFFSET_FILL);
180        glMatrixMode(GL_MODELVIEW);
181        glPopMatrix();
182
183        glMatrixMode(GL_PROJECTION);
184        glPopMatrix();
185
186        glPopAttrib();
187       
188        /*float *data = new float[mSize * mSize];
189
190        GrabDepthBuffer(data, mFbo->GetDepthTex());
191        ExportDepthBuffer(data, mSize);
192
193        delete [] data;
194*/
195        PrintGLerror("shadow map");
196
197        FrameBufferObject::Release();
198}
199
200/*
201void ShadowMapping::Render(RenderTraverser *traverser, Camera *cam)
202{
203        Matrix4x4 cam_proj;
204        Matrix4x4 cam_inverse_modelview;
205
206        const float bias[16] =
207        {0.5f, 0.0f, 0.0f, 0.0f,
208        0.0f, 0.5f, 0.0f, 0.0f,
209        0.0f, 0.0f, 0.5f, 0.0f,
210        0.5f, 0.5f, 0.5f, 1.0f  };
211
212
213        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
214
215        // update the camera, so that the user can have a free look
216        glMatrixMode(GL_MODELVIEW);
217        glLoadIdentity();
218       
219        glMatrixMode(GL_PROJECTION);
220        glLoadIdentity();
221       
222        cam->SetupCameraView();
223
224        // store the inverse of the resulting modelview matrix for the shadow computation
225        glGetFloatv(GL_MODELVIEW_MATRIX, (float *)cam_inverse_modelview.x);
226        cam_inverse_modelview.Invert();
227
228        // bind shadow map
229        glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mFbo->GetDepthTex());
230
231        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
232        //glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_MODE, GL_NONE);
233
234        PrintGLerror("texture");
235
236        //float light_m[16];
237       
238        // compute a matrix that transforms from camera eye space to light clip space
239        // and pass it to the shader through the OpenGL texture matrices, since we
240        // don't use them now
241        glEnable(GL_TEXTURE_2D);
242        glMatrixMode(GL_TEXTURE);
243
244        glLoadMatrixf(bias);
245        glMultMatrixf((float *)mShadowMatrix.x);
246       
247        // multiply the light's (bias * crop * proj * modelview) by the inverse camera modelview
248        // so that we can transform a pixel as seen from the camera
249        glMultMatrixf((float *)cam_inverse_modelview.x);
250       
251               
252        cgGLEnableProfile(RenderState::sCgFragmentProfile);
253        cgGLBindProgram(sCgShadowProgram);
254       
255        cgGLSetTextureParameter(sShadowParam, mFbo->GetDepthTex());
256        cgGLEnableTextureParameter(sShadowParam);
257       
258        // finally, draw the scene
259        traverser->RenderScene();
260
261        cgGLDisableTextureParameter(sShadowParam);
262
263        PrintGLerror("shadow");
264}
265*/
266
267
268//Called to draw scene
269void ShadowMapping::Render(RenderTraverser *traverser, Camera *cam)
270{
271#if 0
272        Matrix4x4 cam_inverse_modelview;
273
274        //Calculate texture matrix for projection
275        //This matrix takes us from eye space to the light's clip space
276        //It is postmultiplied by the inverse of the current view matrix when specifying texgen
277        static Matrix4x4 biasMatrix(0.5f, 0.0f, 0.0f, 0.0f,
278                                                                0.0f, 0.5f, 0.0f, 0.0f,
279                                                                0.0f, 0.0f, 0.5f, 0.0f,
280                                                                0.5f, 0.5f, 0.5f, 1.0f); //bias from [-1, 1] to [0, 1]
281
282        /*glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
283
284        // update the camera, so that the user can have a free look
285        glMatrixMode(GL_MODELVIEW);
286        glLoadIdentity();
287       
288        glMatrixMode(GL_PROJECTION);
289        glLoadIdentity();
290       
291        cam->SetupCameraView();
292*/
293        // store the inverse of the resulting modelview matrix for the shadow computation
294        glGetFloatv(GL_MODELVIEW_MATRIX, (float *)cam_inverse_modelview.x);
295        cam_inverse_modelview.Invert();
296
297        // bind shadow map
298        glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mFbo->GetDepthTex());
299       
300        // compute a matrix that transforms from camera eye space to light clip space
301        // and pass it to the shader through the OpenGL texture matrices, since we
302        // don't use them now
303        glEnable(GL_TEXTURE_2D);
304        glMatrixMode(GL_TEXTURE);
305
306        glLoadMatrixf((float *)biasMatrix.x);
307        glMultMatrixf((float *)mLightViewMatrix.x);
308       
309        // multiply the light's (bias * crop * proj * modelview) by the inverse camera modelview
310        // so that we can transform a pixel as seen from the camera
311        glMultMatrixf((float *)cam_inverse_modelview.x);
312
313        RgbaColor white(1, 1, 1, 0);
314        RgbaColor dark(0.2, 0.2, 0.2, 0);
315
316        glDisable(GL_LIGHTING);
317
318        /*glDisable(GL_LIGHT0);
319        glDisable(GL_LIGHT1);
320
321        //Use dim light to represent shadowed areas
322        glLightfv(GL_LIGHT1, GL_POSITION, mLight->GetDirection());
323        glLightfv(GL_LIGHT1, GL_AMBIENT, (float *)&dark.r);
324        glLightfv(GL_LIGHT1, GL_DIFFUSE, (float *)&white.r);
325        //glLightfv(GL_LIGHT1, GL_SPECULAR, black);
326        glEnable(GL_LIGHT1);
327        glEnable(GL_LIGHTING);*/
328
329        PrintGLerror("firstpass");
330
331        // finally, draw the scene
332        traverser->RenderScene();
333
334
335        glEnable(GL_LIGHTING);
336
337
338        //3rd pass
339        //Draw with bright light
340        //glLightfv(GL_LIGHT1, GL_DIFFUSE, (float *)&white.r);
341        //glLightfv(GL_LIGHT1, GL_SPECULAR, (float *)&white.r);
342
343        Matrix4x4 textureMatrix = biasMatrix * mLightProjectionMatrix * mLightViewMatrix;
344
345        Matrix4x4 texMatT = Transpose(textureMatrix);
346
347        //Set up texture coordinate generation.
348        glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
349        glTexGenfv(GL_S, GL_EYE_PLANE, texMatT.x[0]);
350        glEnable(GL_TEXTURE_GEN_S);
351
352        glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
353        glTexGenfv(GL_T, GL_EYE_PLANE, texMatT.x[1]);
354        glEnable(GL_TEXTURE_GEN_T);
355
356        glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
357        glTexGenfv(GL_R, GL_EYE_PLANE, texMatT.x[2]);
358        glEnable(GL_TEXTURE_GEN_R);
359
360        glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
361        glTexGenfv(GL_Q, GL_EYE_PLANE, texMatT.x[3]);
362        glEnable(GL_TEXTURE_GEN_Q);
363
364        //Bind & enable shadow map texture
365        glBindTexture(GL_TEXTURE_2D, mFbo->GetDepthTex());
366        glEnable(GL_TEXTURE_2D);
367
368        //Enable shadow comparison
369        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
370
371        //Shadow comparison should be true (ie not in shadow) if r<=texture
372        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
373
374        //Shadow comparison should generate an INTENSITY result
375        glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);
376
377        //Set alpha test to discard false comparisons
378        glAlphaFunc(GL_GEQUAL, 0.99f);
379        glEnable(GL_ALPHA_TEST);
380
381        PrintGLerror("texture");
382
383        traverser->RenderScene();
384
385        //Disable textures and texgen
386        glDisable(GL_TEXTURE_2D);
387
388        glDisable(GL_TEXTURE_GEN_S);
389        glDisable(GL_TEXTURE_GEN_T);
390        glDisable(GL_TEXTURE_GEN_R);
391        glDisable(GL_TEXTURE_GEN_Q);
392
393        //Restore other states
394        glDisable(GL_LIGHTING);
395        glDisable(GL_ALPHA_TEST);
396#endif
397}
398
399
400} // namespace
Note: See TracBrowser for help on using the repository browser.