Jump to content
  • Advertisement
Sign in to follow this  
Neutrinohunter

OpenGL Shadow Mapping Woes

This topic is 3814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!