I went through the tutroial at http://www.paulsprojects.net/tutorials/smt/smt.html
but I can’t seem to get it working. Now I even did just a straight copy and paste from the source code provided with the tutorial and it still doesn’t work.
It almost works but there are funny artifacts everywhere.
http://img100.imageshack.us/my.php?image=cameraif2.png
If you look at it from the lights point of view you can see that the projection is off.
http://img413.imageshack.us/my.php?image=lightqc0.png
I also noticed that changing the lights near and far planes for the light projection matrix affects the shadow mapping a lot.
Changing the far plane from 8 to something like 200 seems to make the shadows a little more accurate.
http://img507.imageshack.us/my.php?image=lightcorrecteu1.png
The problem is where the matrices are calculated or where the texGen mapping is happening because the depth map is being generated correctly, at the bottom left of the images there is a picture of the lights depth map.
Heres part of the code:
//Camera & light positions
Vector3D cameraPosition=new Vector3D(-2.5f, 3.5f,-2.5f);
Vector3D lightPosition=new Vector3D(2.0f, 3.0f, -2.0f, 1.0f);
Vector3D white=new Vector3D(1.0f, 1.0f, 1.0f);
Vector3D dimWhite=new Vector3D(0.2f, 0.2f, 0.2f);
Vector3D black=new Vector3D(0.0f, 0.0f, 0.0f);
Matrix4X4 lightProjectionMatrix, lightViewMatrix;
Matrix4X4 cameraProjectionMatrix, cameraViewMatrix;
public int rot=0;
//Size of shadow map
final int shadowMapSize=512;
//Textures
int shadowMapTexture;
//Display lists for objects
int spheresList=-1, torusList=-1, baseList=-1;
public void init(GLAutoDrawable drawable){
GL gl=drawable.getGL();
GLU glu=new GLU();
//Load identity modelview
gl.glMatrixMode(gl.GL_MODELVIEW);
gl.glLoadIdentity();
//Depth states
gl.glClearDepth(1.0f);
gl.glDepthFunc(gl.GL_LEQUAL);
gl.glEnable(gl.GL_DEPTH_TEST);
gl.glEnable(gl.GL_CULL_FACE);
//Create the shadow map texture
gl.glBindTexture(gl.GL_TEXTURE_2D, shadowMapTexture);
gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_DEPTH_COMPONENT, shadowMapSize, shadowMapSize, 0,
gl.GL_DEPTH_COMPONENT, gl.GL_UNSIGNED_BYTE, null);
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP);
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP);
//Calculate & save matrices
gl.glPushMatrix();
gl.glLoadIdentity();
glu.gluPerspective(45.0f, (float)windowWidth/windowHeight, 1.0f, 100.0f);
gl.glGetFloatv(gl.GL_MODELVIEW_MATRIX, cameraProjectionMatrix.m, 0);
gl.glLoadIdentity();
glu.gluLookAt(cameraPosition.x, cameraPosition.y, cameraPosition.z,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f);
gl.glGetFloatv(gl.GL_MODELVIEW_MATRIX, cameraViewMatrix.m, 0);
gl.glLoadIdentity();
glu.gluPerspective(45.0f, 1.0f, 2.0f, 208.0f);
gl.glGetFloatv(gl.GL_MODELVIEW_MATRIX, lightProjectionMatrix.m, 0);
gl.glLoadIdentity();
glu.gluLookAt( lightPosition.x, lightPosition.y, lightPosition.z,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f);
gl.glGetFloatv(gl.GL_MODELVIEW_MATRIX, lightViewMatrix.m, 0);
gl.glPopMatrix();
createObject(gl, new GLUT());
}
public void display(GLAutoDrawable drawable){
GL gl=drawable.getGL();
GLU glu=new GLU();
GLUT glut=new GLUT();
cameraPosition=lightPosition.copy();
gl.glLoadIdentity();
glu.gluLookAt(cameraPosition.x, cameraPosition.y, cameraPosition.z,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f);
gl.glGetFloatv(gl.GL_MODELVIEW_MATRIX, cameraViewMatrix.m, 0);
//First pass - from light's point of view
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(gl.GL_PROJECTION);
gl.glLoadMatrixf(lightProjectionMatrix.m, 0);
gl.glMatrixMode(gl.GL_MODELVIEW);
gl.glLoadMatrixf(lightViewMatrix.m, 0);
//Use viewport the same size as the shadow map
gl.glViewport(0, 0, shadowMapSize, shadowMapSize);
//Draw back faces into the shadow map
gl.glCullFace(gl.GL_FRONT);
//Disable color writes, and use flat shading for speed
gl.glShadeModel(gl.GL_FLAT);
gl.glColorMask(false, false, false, false);
//Draw the scene
DrawScene(gl, glut);
//Read the depth buffer into the shadow map texture
gl.glBindTexture(gl.GL_TEXTURE_2D, shadowMapTexture);
gl.glCopyTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, 0, 0, shadowMapSize, shadowMapSize);
//restore states
gl.glCullFace(gl.GL_BACK);
gl.glShadeModel(gl.GL_SMOOTH);
gl.glColorMask(true, true, true, true);
//2nd pass - Draw from camera's point of view
gl.glClear(gl.GL_DEPTH_BUFFER_BIT);
gl.glViewport(0, 0, windowWidth, windowHeight);
gl.glLoadIdentity();
gl.glMatrixMode(gl.GL_PROJECTION);
gl.glLoadIdentity();
gl.glLoadMatrixf(cameraProjectionMatrix.m, 0);
gl.glMatrixMode(gl.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glLoadMatrixf(cameraViewMatrix.m, 0);
//Use dim light to represent shadowed areas
gl.glLightfv(gl.GL_LIGHT1, gl.GL_POSITION, lightPosition.toFloatArray(), 0);
gl.glLightfv(gl.GL_LIGHT1, gl.GL_AMBIENT, dimWhite.toFloatArray(), 0);
gl.glLightfv(gl.GL_LIGHT1, gl.GL_DIFFUSE, dimWhite.toFloatArray(), 0);
gl.glLightfv(gl.GL_LIGHT1, gl.GL_SPECULAR, black.toFloatArray(), 0);
gl.glEnable(gl.GL_LIGHT1);
gl.glEnable(gl.GL_LIGHTING);
gl.glPushMatrix();
DrawScene(gl, glut);
gl.glPopMatrix();
//3rd pass
//Draw with bright light
gl.glLightfv(gl.GL_LIGHT1, gl.GL_DIFFUSE, white.toFloatArray(), 0);
gl.glLightfv(gl.GL_LIGHT1, gl.GL_SPECULAR, white.toFloatArray(), 0);
//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
Matrix4X4 biasMatrix=new Matrix4X4(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]
//Matrix4X4 textureMatrix=biasMatrix.multiply(lightProjectionMatrix);
//textureMatrix=textureMatrix.multiply(lightViewMatrix);
Matrix4X4 textureMatrix=biasMatrix.multiply(lightProjectionMatrix.multiply(lightViewMatrix));
//Set up texture coordinate generation.
gl.glTexGeni(gl.GL_S, gl.GL_TEXTURE_GEN_MODE, gl.GL_EYE_LINEAR);
gl.glTexGenfv(gl.GL_S, gl.GL_EYE_PLANE, textureMatrix.getRow(0), 0);
gl.glEnable(gl.GL_TEXTURE_GEN_S);
gl.glTexGeni(gl.GL_T, gl.GL_TEXTURE_GEN_MODE, gl.GL_EYE_LINEAR);
gl.glTexGenfv(gl.GL_T, gl.GL_EYE_PLANE, textureMatrix.getRow(1), 0);
gl.glEnable(gl.GL_TEXTURE_GEN_T);
gl.glTexGeni(gl.GL_R, gl.GL_TEXTURE_GEN_MODE, gl.GL_EYE_LINEAR);
gl.glTexGenfv(gl.GL_R, gl.GL_EYE_PLANE, textureMatrix.getRow(2), 0);
gl.glEnable(gl.GL_TEXTURE_GEN_R);
gl.glTexGeni(gl.GL_Q, gl.GL_TEXTURE_GEN_MODE, gl.GL_EYE_LINEAR);
gl.glTexGenfv(gl.GL_Q, gl.GL_EYE_PLANE, textureMatrix.getRow(3), 0);
gl.glEnable(gl.GL_TEXTURE_GEN_Q);
//Bind & enable shadow map texture
gl.glBindTexture(gl.GL_TEXTURE_2D, shadowMapTexture);
gl.glEnable(gl.GL_TEXTURE_2D);
//Enable shadow comparison
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_COMPARE_MODE_ARB, gl.GL_COMPARE_R_TO_TEXTURE);
//Shadow comparison should be true (ie not in shadow) if r<=texture
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_COMPARE_FUNC_ARB, gl.GL_LEQUAL);
//Shadow comparison should generate an INTENSITY result
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_DEPTH_TEXTURE_MODE_ARB, gl.GL_INTENSITY);
//Set alpha test to discard false comparisons
gl.glAlphaFunc(gl.GL_GEQUAL, 0.99f);
gl.glEnable(gl.GL_ALPHA_TEST);
DrawScene(gl, glut);
//Disable textures and texgen
gl.glDisable(gl.GL_TEXTURE_2D);
gl.glDisable(gl.GL_TEXTURE_GEN_S);
gl.glDisable(gl.GL_TEXTURE_GEN_T);
gl.glDisable(gl.GL_TEXTURE_GEN_R);
gl.glDisable(gl.GL_TEXTURE_GEN_Q);
//Restore other states
gl.glDisable(gl.GL_LIGHTING);
gl.glDisable(gl.GL_ALPHA_TEST);
//reset matrices
gl.glMatrixMode(gl.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(gl.GL_MODELVIEW);
gl.glPopMatrix();
gl.glFinish();
}
public void DrawScene(GL gl, GLUT glut){
//Draw objects
gl.glPushMatrix();
gl.glCallList(baseList);
gl.glPopMatrix();
gl.glPushMatrix();
gl.glCallList(torusList);
gl.glPopMatrix();
gl.glPushMatrix();
gl.glRotatef(rot, 0.0f, 1.0f, 0.0f);
gl.glCallList(spheresList);
gl.glPopMatrix();
}
}