PDA

View Full Version : Shadow moving with player - Shadowmapping



uwi2k2
02-22-2013, 05:44 AM
hi all,

i just try to get a propper shadowmapping in my game.
I copyed all the logik from a other example that works fine ..
but as a result the shadow is moving strangly with the player/mouse movment ..
So im quite sure this a matrix math problem .. but i just cant see whats wron with my calc.

I guess aPicture will not help her, so i made a small video:
http://youtu.be/4x0XXZ0VVvA

As the complete script would be to long, ill try to show the important points in the right order.


// Frame Start

1. Load identyty for all matrix variables that are used in the frame

2. Bind my Shadowmap Framebuffer

3. Set Perspectiv for 'Light World':


setPerspectiv( ShadowMapSize, ShadowMapSize);
>> here is the function
void setPerspectiv(int Width, int Height)
{
glViewport(0, 0, Width, Height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluPerspective( 60.0, float(Width) / float(Height), 1.0f, 100.0f );

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

4. Save Light-Project Matrix :

glGetFloatv( GL_PROJECTION_MATRIX , (GLfloat*)&m_LightProjection );

5. Set Camera to Light View:

gluLookAt( 10.0f, 5.0f, 10.0f,
2.0f, 2.0f, 2.0f,
0.0, 1.0, 0.0 );

6. Save Light View Matrix:

glGetFloatv( GL_MODELVIEW_MATRIX , (GLfloat*)&m_LightView );

7. Set Perspectiv to Playes World :

setPerspectiv( CurrentWidth, CurrentHeight );

8. Set Camera to Player 3rd Person Vie:

gluLookAt( xpos-float(sin(yrotrad)*8.0), (ypos+float(sin(xrotrad)*18.0)*yMultiplyer)+8.4f, zpos+float(cos(yrotrad)*8.0),
xpos, ypos+4.4f, zpos,
0.0, 1.0, 0.0 );

9. Save Player View Matrix:

glGetFloatv( GL_MODELVIEW_MATRIX , (GLfloat*)&m_View );

10. Invert Player View Matrix:

bool inverting = InvertMatrix( (GLfloat*)&m_View.m[0][0] , (GLfloat*)&mViewInv.m[0][0] );
>> i just copyed this function from gluInverMatrix();

11. Calculate the ShadowTexture Matrix:

// Formular >> mTextureMatrix = m_BiasMatrix * m_LightProjection * m_LightView * mViewInv;
Matrix3DMultiply( &tmpMatrix , &m_BiasMatrix , &m_LightProjection );
Matrix3DMultiply( &tmpMatrix , &tmpMatrix , &m_LightView );
Matrix3DMultiply( &tmpMatrix , &tmpMatrix , &mViewInv );
mTextureMatrix = tmpMatrix;
// basis matrix looks like this:
Matrix3D m_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};


12. Use Shader Programm and Set Uniforms:

glUseProgram(ProgramId);
glUniformMatrix4fv( s_u_TexProjectionMatrix, 1, GL_FALSE, (GLfloat*)&mTextureMatrix );
glActiveTexture ( GL_TEXTURE2 );
glBindTexture( GL_TEXTURE_2D , m_uiShadowMapTexture );
glUniform1i ( s_s_ShadowTexture, 2 );
glUniform1i ( s_u_shadowUse, 1 );

13. Draw Models like this:

// enable vertex attrib, set AttribPointers
// bind other textures
glPushMatrix();
// do translate and rotate with: glTranslatef() , glRotatef()
// get modelView matrix to shader
glGetFloatv( GL_MODELVIEW_MATRIX , this->modellMatrix );
glUniformMatrix4fv( this->m_u_modelMatrixLoc, 1, GL_FALSE, (GLfloat*)&this->modellMatrix );
glPopMatrix();

// get perspectiv matrix to shader
glGetFloatv( GL_PROJECTION_MATRIX , this->projectMatrix );
glUniformMatrix4fv( this->m_u_perspectMatrixLoc, 1, GL_FALSE, (GLfloat*)&this->projectMatrix );

// draw it
glDrawArrays( GL_TRIANGLES, 0, this->VertexCount ); // this->VertexCount

14. Use Data in Vertex Shader:

attribute vec4 in_Position;
attribute vec3 in_Normal;
attribute vec2 in_TextCoord;

uniform mat4 pers_Matrix;
uniform mat4 model_Matrix;
uniform highp mat4 TexProjectionMatrix;
uniform sampler2D s_mainTexture;
uniform vec3 LightDirection;
uniform bool shadowUse;

varying vec3 interp_Normal;
varying vec2 interp_TextCoord;
varying mat4 tmp_matrix;
varying highp vec4 projCoord;
varying float LightIntensity;
varying float doFragmentCalc;

void main(void)
{
if( shadowUse )
{
highp vec4 modelViewPos = model_Matrix * vec4( in_Position.xyz , 1.0 );
projCoord = TexProjectionMatrix * modelViewPos;
}

interp_Normal = in_Normal ;
interp_TextCoord = in_TextCoord ;
gl_Position = pers_Matrix * model_Matrix * in_Position ;

// Simple diffuse lighting in model space
LightIntensity = dot( in_Normal, -LightDirection ) + 0.4;
}

15. Use Data in Fragment Shader:

uniform mat4 pers_Matrix;
uniform mat4 model_Matrix;
uniform sampler2D s_mainTexture;
uniform sampler2D s_specTexture;
uniform highp sampler2D s_ShadowTexture;
uniform bool specTextureInUse;
uniform bool shadowUse;

varying vec4 interp_Normal;
varying vec2 interp_TextCoord;
varying mat4 tmp_matrix;
varying highp vec4 projCoord;
varying float LightIntensity;
varying float doFragmentCalc;

void main(void)
{
lowp float val = 1.0;

if( shadowUse )
{
// Subtract a small magic number to account for floating-point error
highp float comp = ( projCoord.z / projCoord.w ) - 0.03;
highp float depth = texture2DProj( s_ShadowTexture, projCoord ).r;
//val = (comp <= depth ? 1.0 : 0.4 ); // this fails because of wrong values i guess
val = ( depth > 0.83 ? 1.0 : 0.4 ); // << so just show the shadow texture
}

gl_FragColor = texture2D( s_mainTexture, interp_TextCoord ) * LightIntensity * val ;
gl_FragColor.a = 1.0;

if( specTextureInUse )
gl_FragColor.rgb += ( texture2D( s_specTexture, interp_TextCoord ).r / 5 ) * LightIntensity;
}


You can see the result of all this in the video ...
Im very shure its just a math miss-calculation ...

This keeps me busy now for some time ... pls give me a hint what i need to change ..

Thanx very mutch !!!

uwi

Dark Photon
02-22-2013, 06:11 PM
2. Bind my Shadowmap Framebuffer

3. Set Perspectiv for 'Light World':

Uh oh. Looks like you're trying to simulate a directional light source. That would be an Orthographic projection for the light, not Perspective.



highp float comp = ( projCoord.z / projCoord.w ) - 0.03;
highp float depth = texture2DProj( s_ShadowTexture, projCoord ).r;


With orthographic, you don't need Proj or divide-by-w.



Matrix3D m_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};

Check the conventions of your math library to ensure that that translate is where it should be in this matrix. Your matrix order makes me suspicious that it might not be.

uwi2k2
02-23-2013, 02:15 AM
hi,

thanx for the feedback,

yess i will move to ortho. Shadow map ...

but finally i made it.. it turned out that the matrix multiply needed to be done in invers order ...
i knew it was a stuoid solution :-(

here is the result: http://www.youtube.com/watch?v=yopg_auy6Fg

still need to smoth the shadow ..

thanx
uwi

Dark Photon
02-23-2013, 05:06 PM
still need to smoth the shadow ..

You can use GPU supported PCF for starters. That is, enable depth comparisons for your shadow depth texture and set LINEAR MIN/MAG filters on it (that means do PCF filtering):


glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE , GL_INTENSITY );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR );


change the s_ShadowTexture sampler2D uniform to sampler2DShadow in the shader, and change your texture2D call to shadow2D (in a more modern GLSL profile, you'd just use the same "texture" call), passing it a vec3 texcoord containing x, y, and depth. Then the GPU will sample multiple pixels, do the depth comparison internally, and provide you back an average visibility.

It's not perfect, but it's better than nothing. For better filtering, read up on VSM and ESM.