Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 4 of 4

Thread: Shadow moving with player - Shadowmapping

  1. #1
    Intern Contributor uwi2k2's Avatar
    Join Date
    Mar 2011
    Posts
    98

    Shadow moving with player - Shadowmapping

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

    Code :
      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 :
    Code :
            glGetFloatv( GL_PROJECTION_MATRIX , (GLfloat*)&m_LightProjection );

    5. Set Camera to Light View:
    Code :
            gluLookAt(  10.0f, 5.0f, 10.0f,
                            2.0f, 2.0f, 2.0f, 
                            0.0, 1.0, 0.0 );

    6. Save Light View Matrix:
    Code :
            glGetFloatv( GL_MODELVIEW_MATRIX , (GLfloat*)&m_LightView );

    7. Set Perspectiv to Playes World :
    Code :
         setPerspectiv( CurrentWidth, CurrentHeight );

    8. Set Camera to Player 3rd Person Vie:
    Code :
              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:
    Code :
            glGetFloatv( GL_MODELVIEW_MATRIX , (GLfloat*)&m_View );

    10. Invert Player View Matrix:
    Code :
            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:
    Code :
         // 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:
    Code :
             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:
    Code :
            // 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:
    Code :
         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:
    Code :
         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
    Last edited by uwi2k2; 02-22-2013 at 06:45 AM. Reason: wrong url
    uwi2k2 - OpenGL Trainer: www.opengl-trainer.com
    ---------------------------------------------------------
    Free Programming Helpline: www.programming-hotline.com
    ---------------------------------------------------------
    A Friday Night Programmer: www.uwiworld.net

  2. #2
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,211
    Quote Originally Posted by uwi2k2 View Post
    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.

    Code glsl:
    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.

    Code cpp:
    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.
    Last edited by Dark Photon; 02-22-2013 at 07:24 PM.

  3. #3
    Intern Contributor uwi2k2's Avatar
    Join Date
    Mar 2011
    Posts
    98
    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
    uwi2k2 - OpenGL Trainer: www.opengl-trainer.com
    ---------------------------------------------------------
    Free Programming Helpline: www.programming-hotline.com
    ---------------------------------------------------------
    A Friday Night Programmer: www.uwiworld.net

  4. #4
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,211
    Quote Originally Posted by uwi2k2 View Post
    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):

    Code cpp:
       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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •