Shadow Mapping Woes

Started by
2 comments, last by Neutrinohunter 16 years, 3 months ago
I am currently trying to incorporate simple Shadow Mapping into my "engine" and am stumpling into problems which I'm not sure how to fix. Not sure whether my OpenGL code is wrong or my interpretation. I have read various different papers on this, describing various different terms: Cascading, Perspective, Adaptive, Forward, Variance, Deep, Parallel-Split, Trapezoidal and finally Back-projection. I know they all are based on the generic Shadow Mapping algorithm, but how do they differ? 1st Problem) I have a setup such as the following render() { for each light { Setup Projection and View Matrices with respect to the light renderScene into depth buffer clear buffer Setup with respect to the Camera draw scene } } Open GL Code

void JShadowMappingAlgorithm2::render(GLfloat x, GLfloat y, GLfloat z) {
   JLightManager * lightManager = scene->getLightManager();
   int numberOfLights = lightManager->getNumberOfLightsUsed();
   JModelManager * modelManager = scene->getModelManager();

   //INITIALISATION STEP HAS TO BE DONE EACH TIME BECAUSE THE CAMERA
   //IS NOT STATIONARY!!!!!!!!!! YOU NITWIT!

   //Load identity modelview
	
	//Calculate & save matrices
	glPushMatrix();
      glLoadIdentity();
      gluPerspective(45.0, 1.0, 0.1, 1000.0);
      glGetFloatv(GL_MODELVIEW_MATRIX, cameraProjectionMatrix);
	   glLoadIdentity();


      JVector3D pos = scene->getCameraManager()->getCurrentCamera()->getCameraPosition();
      JVector3D dir = scene->getCameraManager()->getCurrentCamera()->getCameraDirection();
      gluLookAt(pos.x, pos.y, pos.z,
				dir.x, dir.y, dir.z,
				0.0f, 1.0f, 0.0f);
      glGetFloatv(GL_MODELVIEW_MATRIX, cameraViewMatrix);
      glLoadIdentity();


   	gluPerspective(45.0, 1.0, 0.1, 1000.0);
   	glGetFloatv(GL_MODELVIEW_MATRIX, lightProjectionMatrix);
      glLoadIdentity();
   
      JVector3D lightPos = scene->getLightManager()->getLight(0)->getPosition();
	   gluLookAt(lightPos.x, lightPos.y, lightPos.z,
				0.0f, 0.0f, 0.0f,
				0.0f, 1.0f, 0.0f);
	  glGetFloatv(GL_MODELVIEW_MATRIX, lightViewMatrix);
	
	glPopMatrix();

   /////////////////////////////////////////////////////////////////////////

   GLint viewport[4];
   glGetIntegerv(GL_VIEWPORT, viewport);
   for(int i = 0; i < numberOfLights; i++) {
      JVector3D lightPos = lightManager->getLight(i)->getPosition();
	  //First pass - from light's point of view
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      glLoadIdentity();
      glMatrixMode(GL_PROJECTION);
      glLoadMatrixf(lightProjectionMatrix);
      glMatrixMode(GL_MODELVIEW);
      glLoadMatrixf(lightViewMatrix);

      //Use viewport the same size as the shadow map
      glViewport(0, 0, SHADOW_MAP_WIDTH, SHADOW_MAP_HEIGHT);

      //Draw back faces into the shadow map
      glCullFace(GL_FRONT);

      //Disable color writes, and use flat shading for speed
      glShadeModel(GL_FLAT);
      glColorMask(0, 0, 0, 0);
	
      scene->renderInternalProperties();
      modelManager->render();

      //Read the depth buffer into the shadow map texture
   	glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
      glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,SHADOW_MAP_WIDTH, SHADOW_MAP_HEIGHT);

      //restore states
      glCullFace(GL_BACK);
      glShadeModel(GL_SMOOTH);
      glColorMask(1, 1, 1, 1);

      //bool showShadowMap = true;
//      if (showShadowMap)
//        return;
	
      //2nd pass - Draw from camera's point of view
      glClear(GL_DEPTH_BUFFER_BIT);

      glMatrixMode(GL_PROJECTION);
      glLoadMatrixf(cameraProjectionMatrix);
	
      glMatrixMode(GL_MODELVIEW);
      glLoadMatrixf(cameraViewMatrix);

      //glViewPort(0, 0, winWidth, winHeight);
      glViewport( viewport[0], viewport[1], viewport[2], viewport[3] );

      //Use dim light to represent shadowed areas
      GLfloat lightPosition [] = {lightPos.x, lightPos.y, lightPos.z, 1.0};
      glLightfv(GL_LIGHT0+i, GL_POSITION, lightPosition );
      GLfloat white [] = {0.2,0.2,0.2,1.0};
      GLfloat black [] = {0.0,0.0,0.0,1.0};
      glLightfv(GL_LIGHT0+i, GL_AMBIENT, white);
      glLightfv(GL_LIGHT0+i, GL_DIFFUSE, white);
      glLightfv(GL_LIGHT0+i, GL_SPECULAR, black);
      glEnable(GL_LIGHT0+i);
      glEnable(GL_LIGHTING);

      scene->renderInternalProperties();
   	modelManager->render();
	
      GLfloat cwhite [] = { 1.0,1.0,1.0,1.0};
      GLfloat cblack [] = {0.0,0.0,0.0,1.0};
      //3rd pass
      //Draw with bright light
      glLightfv(GL_LIGHT0+i, GL_DIFFUSE, cwhite);
      glLightfv(GL_LIGHT0+i, GL_SPECULAR, cwhite);

      //Calculate texture matrix for projection
      //This matrix takes us from eye space to the light's clip space
      //It is postmultiplied by the inverse of the current view matrix when specifying texgen
      static MATRIX4X4 biasMatrix(0.5f, 0.0f, 0.0f, 0.0f,
								0.0f, 0.5f, 0.0f, 0.0f,
								0.0f, 0.0f, 0.5f, 0.0f,
								0.5f, 0.5f, 0.5f, 1.0f);	//bias from [-1, 1] to [0, 1]
      Matrix textureMatrix=biasMatrix*lightProjectionMatrix*lightViewMatrix;

      //Set up texture coordinate generation.
      glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
      glTexGenfv(GL_S, GL_EYE_PLANE, textureMatrix.GetRow(0));
      glEnable(GL_TEXTURE_GEN_S);

      glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
      glTexGenfv(GL_T, GL_EYE_PLANE, textureMatrix.GetRow(1));
      glEnable(GL_TEXTURE_GEN_T);

      glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
      glTexGenfv(GL_R, GL_EYE_PLANE, textureMatrix.GetRow(2));
      glEnable(GL_TEXTURE_GEN_R);

      glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
      glTexGenfv(GL_Q, GL_EYE_PLANE, textureMatrix.GetRow(3));
      glEnable(GL_TEXTURE_GEN_Q);

      //Bind & enable shadow map texture
      glBindTexture(GL_TEXTURE_2D, shadowMapTexture);
      glEnable(GL_TEXTURE_2D);

      //Enable shadow comparison
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);

      //Shadow comparison should be true (ie not in shadow) if r<=texture
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);

      //Shadow comparison should generate an INTENSITY result
      glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);

      //Set alpha test to discard false comparisons
      glAlphaFunc(GL_GEQUAL, 0.99f);
      glEnable(GL_ALPHA_TEST);

      //glDisable(GL_TEXTURE_2D);
      ///glMatrixMode(GL_MODELVIEW);
      //glLoadIdentity();
      //scene->getCurrentCamera()->Update();
      scene->renderInternalProperties();
   	modelManager->render(true);

      //Disable textures and texgen
      glDisable(GL_TEXTURE_2D);

      glDisable(GL_TEXTURE_GEN_S);
      glDisable(GL_TEXTURE_GEN_T);
      glDisable(GL_TEXTURE_GEN_R);
      glDisable(GL_TEXTURE_GEN_Q);

      //Restore other states
      glDisable(GL_LIGHTING);
      glDisable(GL_ALPHA_TEST);
   }     
}

I have 3 passes in the above algorithm to add extra light to the scene. Is there anything wrong with the code or just biasing or matrix trouble as I have no outputted shadow. Neutrinohunter
Advertisement
They can differ in projection organization:

Dual parabolic (two shadowmaps for each halfsphere around a point lightwith parabolic projection, not artifact free)

Cascading (many shadowmaps for directional lights, to avoid under and oversampling. Disadvantage: Many render passes)

Trapezoidal, Perspective... (desperate trys to construct a adaptive projection matrix. All these algorithms suck if the near plane is covered in light direction by the farplane. This case can't be avoided if the user can rotate the cam.)


Variance shadowmapping, this allows to filter shadowmaps with blur, anisotropic and mipmapping filter. Has it's own artifacts, but is most times better than standard filtering. It can be combined with all projections.
Thanks for the info, is there anything I'm doing which is drastically wrong in my code?

Neutrinohunter
Anybody have any input about the code? I still for the life of me can't see anything wrong.
Neutrinohunter

This topic is closed to new replies.

Advertisement