shadow map problem

kangcool

Newcomer
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:

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;
}
 
Back
Top