trying to get shadow map working but it does not work.
Not sure what i am doing wrong as it based on the superbible code and that works where as mine does not.
Any help would be greatly apprecated!
code below:
Not sure what i am doing wrong as it based on the superbible code and that works where as mine does not.
Any help would be greatly apprecated!
code below:
Code:
#include <math.h>
#include <stdio.h>
#include <GL/glut.h>
#include <GL/glext.h>
#define WALL 20.0
#define WALL1 30.0
#define GL_DEPTH_TEXTURE_MODE 0x884B
#define GL_TEXTURE_COMPARE_MODE 0x884C
#define GL_COMPARE_R_TO_TEXTURE 0x884E
#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
/* enums */
enum {
X, Y, Z, W
};
enum {
A, B, C, D
};
GLfloat floor_quad[4 * 3] = {
-WALL1, 0.0, -WALL1,
-WALL1, 0.0, WALL1,
WALL1, 0.0, WALL1,
WALL1, 0.0, -WALL1
};
// Globals
GLboolean ambientShadowAvailable = GL_TRUE;
GLfloat floor_plane[4];
GLfloat* light_samples;
GLuint light_size = 4.0;
//GLfloat light_position[4] = { WALL, WALL, WALL, 1.0 };
//GLfloat light_position[4] = { 0.0, 50.0, 20.0, 1.0 };
GLfloat light_position[4] = { 40.0, 50.0, 10.0, 1.0 };
GLuint num_samples = 512;
GLint shadowSize = 512;
GLuint shadowTextureID;
GLfloat factor = 4.0f; // polygon offset fun
GLint windowWidth = 512; // window size
GLint windowHeight = 512;
GLuint floor_list = 0; /* display list for floor */
GLuint floor_shadow_list = 0; /* display list for shadows on floor */
GLuint ball_grid_list = 0; /* display list for grid of balls */
GLboolean texturing = GL_FALSE;
GLboolean draw_sample_vectors = GL_FALSE;
GLboolean view_from_light = GL_FALSE;
GLboolean draw_shadows = GL_TRUE;
GLboolean frame_rate = GL_FALSE;
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f};
GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f};
// Maths stuff
void
normalize(GLfloat* n)
{
GLfloat l;
/* normalize */
l = (GLfloat)sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
n[0] /= l;
n[1] /= l;
n[2] /= l;
}
void
cross(GLfloat* u, GLfloat* v, GLfloat* n)
{
/* compute the cross product (u x v for right-handed [ccw]) */
n[0] = u[1] * v[2] - u[2] * v[1];
n[1] = u[2] * v[0] - u[0] * v[2];
n[2] = u[0] * v[1] - u[1] * v[0];
}
// Functions
void
planeequation(GLfloat plane[4], GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
{
GLfloat vec0[3], vec1[3];
/* need 2 vectors to find cross product */
vec0[0] = v1[0] - v0[0];
vec0[1] = v1[1] - v0[1];
vec0[2] = v1[2] - v0[2];
vec1[0] = v2[0] - v0[0];
vec1[1] = v2[1] - v0[1];
vec1[2] = v2[2] - v0[2];
/* find cross product to get A, B, and C of plane equation */
plane[0] = vec0[1] * vec1[2] - vec0[2] * vec1[1];
plane[1] = -(vec0[0] * vec1[2] - vec0[2] * vec1[0]);
plane[2] = vec0[0] * vec1[1] - vec0[1] * vec1[0];
plane[3] = -(plane[0] * v0[0] + plane[1] * v0[1] + plane[2] * v0[2]);
}
GLfloat*
samplelight(GLuint samples, GLuint size, GLfloat light[4])
{
static GLfloat* lights = NULL;
GLuint i, j, sqrt_samples;
GLfloat x, y;
GLfloat n[3], u[3], v[3];
/* allocate new array for light samples */
if (lights)
free(lights);
lights = (GLfloat*)malloc(sizeof(GLfloat) * 4 * samples);
/* take care of a simple case */
if (samples == 1) {
lights[0] = light[0];
lights[1] = light[1];
lights[2] = light[2];
lights[3] = 1.0;
return lights;
}
/* calculate the vectors that define the area light (just a plane
with sides of size): u is up, v is across */
n[0] = light[0];
n[1] = light[1] + 10;
n[2] = light[2] + 30;
normalize(n);
u[0] = 0.0; u[1] = 1.0; u[2] = 0.0;
cross(u, n, v); normalize(v);
cross(n, v, u); normalize(u);
/* unitize the vectors */
v[0] *= size/2.0; v[1] *= size/2.0; v[2] *= size/2.0;
u[0] *= size/2.0; u[1] *= size/2.0; u[2] *= size/2.0;
/* sample on a regular grid */
sqrt_samples = (GLuint)sqrt(samples);
y = -1.0 + 2.0 / sqrt_samples;
for (j = 0; j < sqrt_samples; j++) {
x = -1.0 + 2.0 / sqrt_samples;
for (i = 0; i < sqrt_samples; i++) {
lights[4 * (j * sqrt_samples + i) + 0] = light[0] + x * v[0] + y * u[0];
lights[4 * (j * sqrt_samples + i) + 1] = light[1] + x * v[1] + y * u[1];
lights[4 * (j * sqrt_samples + i) + 2] = light[2] + x * v[2] + y * u[2];
lights[4 * (j * sqrt_samples + i) + 3] = 1.0;
x += 2.0 / sqrt_samples;
}
y += 2.0 / sqrt_samples;
}
return lights;
}
void
level(float x)
{
float i = x * 7.0;
glPushMatrix();
glTranslatef(20.0, (20.0 + i), 17.0);
glColor3f(0.0, 1.0, 0.0);
glutSolidSphere(2.0, 8, 8);
glPopMatrix();
glPushMatrix();
glTranslatef(20.0, (20.0 + i), 3.0);
glColor3f(0.0, 1.0, 0.0);
glutSolidSphere(2.0, 8, 8);
glPopMatrix();
glPushMatrix();
glTranslatef(20.0, (20.0 + i), 10.0);
glColor3f(0.0, 0.0, 1.0);
glutSolidSphere(2.0, 8, 8);
glPopMatrix();
glPushMatrix();
glTranslatef(27.0, (20.0 + i), 3.0);
glColor3f(1.0, 0.0, 0.0);
glutSolidSphere(2.0, 8, 8);
glPopMatrix();
glPushMatrix();
glTranslatef(27.0, (20.0 + i), 10.0);
glColor3f(1.0, 1.0, 0.0);
glutSolidSphere(2.0, 8, 8);
glPopMatrix();
glPushMatrix();
glTranslatef(27.0, (20.0 + i), 17.0);
glColor3f(1.0, 1.0, 0.0);
glutSolidSphere(2.0, 8, 8);
glPopMatrix();
glPushMatrix();
glTranslatef(34.0, (20.0 + i), 3.0);
glColor3f(1.0, 0.0, 0.0);
glutSolidSphere(2.0, 8, 8);
glPopMatrix();
glPushMatrix();
glTranslatef(34.0, (20.0 + i), 10.0);
glColor3f(1.0, 1.0, 0.0);
glutSolidSphere(2.0, 8, 8);
glPopMatrix();
glPushMatrix();
glTranslatef(34.0, (20.0 + i), 17.0);
glColor3f(1.0, 1.0, 0.0);
glutSolidSphere(2.0, 8, 8);
glPopMatrix();
}
void
grid()
{
level(0.0);
level(1.0);
level(2.0);
}
GLvoid
displaywalls()
{
glCallList(floor_list);
glCallList(ball_grid_list);
}
void
lists()
{
ball_grid_list = glGenLists(1);
glNewList(ball_grid_list, GL_COMPILE);
grid();
glEndList();
/* floor shadow */
floor_shadow_list = glGenLists(1);
glNewList(floor_shadow_list, GL_COMPILE);
grid();
glPushMatrix();
glTranslatef(10.0, 5.0, 2.0);
glColor3f(1.0, 1.0, 0.0);
glutSolidSphere(light_size / 2.0, 8, 8);
glPopMatrix();
//grid();
glEndList();
/* floor */
floor_list = glGenLists(1);
glNewList(floor_list, GL_COMPILE);
glColor3f(1.0, 1.0, 0.7);
glBegin(GL_QUADS);
glNormal3f(0.0, 1.0, 0.0);
glTexCoord2f(0.0, 0.0);
glVertex3fv(&floor_quad[3 * 0]);
glTexCoord2f(1.0, 0.0);
glVertex3fv(&floor_quad[3 * 1]);
glTexCoord2f(1.0, 1.0);
glVertex3fv(&floor_quad[3 * 2]);
glTexCoord2f(0.0, 1.0);
glVertex3fv(&floor_quad[3 * 3]);
glEnd();
glEndList();
}
void makeShadowMap( void )
{
GLfloat lightModelView[16], lightProjection[16];
GLfloat lightToSceneDistance, nearPlane, fieldOfView;
lightToSceneDistance = sqrt(light_position[0] * light_position[0] +
light_position[1] * light_position[1] +
light_position[2] * light_position[2]);
nearPlane = lightToSceneDistance - 150.0f;
//fprintf(stdout, " %.1f Plane \r\n", nearPlane);
if(nearPlane < 50.0f)
{
nearPlane = 5.0f;
}
//fprintf(stdout, " %.1f Plane \r\n", nearPlane);
fieldOfView = 17000.0f / lightToSceneDistance;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fieldOfView, 1.0f, nearPlane, nearPlane + 100.0f);
glGetFloatv(GL_PROJECTION_MATRIX, lightProjection);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(light_position[0], light_position[1], light_position[2],
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glGetFloatv(GL_MODELVIEW_MATRIX, lightModelView);
glViewport(0, 0, shadowSize, shadowSize);
// Clear the window with current clearing color
glClear(GL_DEPTH_BUFFER_BIT);
// All we care about here is resulting depth values
glShadeModel(GL_FLAT);
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_NORMALIZE);
glColorMask(0, 0, 0, 0);
// Overcome imprecision
glEnable(GL_POLYGON_OFFSET_FILL);
// Draw objects in the scene
displaywalls();
// Copy depth values into depth texture
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
0, 0, shadowSize, shadowSize, 0);
// Restore normal drawing state
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
glColorMask(1, 1, 1, 1);
glDisable(GL_POLYGON_OFFSET_FILL);
// Set up texture matrix for shadow map projection
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(0.5f, 0.5f, 0.5f);
glScalef(0.5f, 0.5f, 0.5f);
glMultMatrixf(lightProjection);
glMultMatrixf(lightModelView);
}
void
init(void)
{
lists();
planeequation(floor_plane,
&floor_quad[3*0], &floor_quad[3*1], &floor_quad[3*2]);
light_samples = samplelight(num_samples, light_size, light_position);
// Black background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
// Hidden surface removal
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glPolygonOffset(factor, 0.0f);
// Set up some lighting state that never changes
glShadeModel(GL_SMOOTH);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_NORMALIZE);
glEnable(GL_LIGHT0);
// Set up some texture state that never changes
glGenTextures(1, &shadowTextureID);
glBindTexture(GL_TEXTURE_2D, shadowTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
if (ambientShadowAvailable)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB,
0.5f);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
makeShadowMap();
}
void
reshape(int width, int height)
{
//tbReshape(width, height);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)height / (GLfloat)width, 1.0, 128.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, -10.0, -30.0);
glRotatef(-20.0, 0.0, 1.0, 0.0);
}
void
display(void)
{
static GLuint i;
static int start, end;
start = glutGet(GLUT_ELAPSED_TIME);
// old stuff
gluLookAt(30.0, 20.0, 20.0,
0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
/* do the trackball rotation. */
//glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Show the shadowMap at its actual size relative to window
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(((GLfloat)shadowSize/(GLfloat)windowWidth)*2.0-1.0f,
-1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(((GLfloat)shadowSize/(GLfloat)windowWidth)*2.0-1.0f,
((GLfloat)shadowSize/(GLfloat)windowHeight)*2.0-1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(-1.0f,
((GLfloat)shadowSize/(GLfloat)windowHeight)*2.0-1.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
//gluPerspective(45.0f, 1.0f, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
GLfloat sPlane[4] = {1.0f, 0.0f, 0.0f, 0.0f};
GLfloat tPlane[4] = {0.0f, 1.0f, 0.0f, 0.0f};
GLfloat rPlane[4] = {0.0f, 0.0f, 1.0f, 0.0f};
GLfloat qPlane[4] = {0.0f, 0.0f, 0.0f, 1.0f};
if (!ambientShadowAvailable)
{
GLfloat lowAmbient[4] = {0.1f, 0.1f, 0.1f, 1.0f};
GLfloat lowDiffuse[4] = {0.35f, 0.35f, 0.35f, 1.0f};
// Because there is no support for an "ambient"
// shadow compare fail value, we'll have to
// draw an ambient pass first...
glLightfv(GL_LIGHT0, GL_AMBIENT, lowAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lowDiffuse);
// Draw objects in the scene
displaywalls();
// Enable alpha test so that shadowed fragments are discarded
glAlphaFunc(GL_GREATER, 0.9f);
glEnable(GL_ALPHA_TEST);
}
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
// Set up shadow comparison
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Set up the eye plane for projecting the shadow map on the scene
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
glTexGenfv(GL_T, GL_EYE_PLANE, tPlane);
glTexGenfv(GL_R, GL_EYE_PLANE, rPlane);
glTexGenfv(GL_Q, GL_EYE_PLANE, qPlane);
// Draw objects in the scene
displaywalls();
glDisable(GL_ALPHA_TEST);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
/* draw a yellow sphere for the light */
glDisable(GL_LIGHTING);
glPushMatrix();
glTranslatef(light_position[0], light_position[1], light_position[2]);
glColor3f(1.0, 1.0, 0.0);
glutSolidSphere(light_size / 2.0, 8, 8);
glPopMatrix();
//glEnable(GL_LIGHTING);
/* draw the scene */
//glPopMatrix();
glutSwapBuffers();
// gluLookAt(30.0, 20.0, 20.0,
// 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glFinish();
/* make sure rendering is done */
end = glutGet(GLUT_ELAPSED_TIME);
fprintf(stderr, " %.1f fps \r",
1.0 / ((double)(end - start) / 1000.0));
}
void
keyboard(char key, int x, int y)
{
switch (key) {
case 'h':
printf("shadow help\n\n");
printf("escape or q - Quit\n\n");
break;
case 'q':
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
int
main(int argc, char** argv)
{
int buffer = GLUT_SINGLE;
glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitDisplayMode(GLUT_RGB | buffer | GLUT_DEPTH | GLUT_STENCIL | GLUT_MULTISAMPLE);
glutCreateWindow("Fuzzy Shadow");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
init();
glutMainLoop();
return 0;
}