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 |
|
---|
9 | using namespace std;
|
---|
10 |
|
---|
11 |
|
---|
12 | namespace CHCDemoEngine
|
---|
13 | {
|
---|
14 |
|
---|
15 | static GLenum mrt[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT};
|
---|
16 |
|
---|
17 | static 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 |
|
---|
31 | static CGprogram sCgShadowProgram;
|
---|
32 | static CGparameter sShadowParam;
|
---|
33 |
|
---|
34 |
|
---|
35 | static 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 |
|
---|
47 | static 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 |
|
---|
81 | ShadowMapping::ShadowMapping(const AxisAlignedBox3 &sceneBox, int size):
|
---|
82 | mSceneBox(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 |
|
---|
93 | ShadowMapping::~ShadowMapping()
|
---|
94 | {
|
---|
95 | //if (sCgShadowProgram) cgDestroyProgram(sCgShadowProgram);
|
---|
96 | DEL_PTR(mFbo);
|
---|
97 | }
|
---|
98 |
|
---|
99 |
|
---|
100 | void 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 |
|
---|
122 | void 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 | /*
|
---|
201 | void 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
|
---|
269 | void 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
|
---|