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 5 of 5

Thread: Directional light and shadow mapping view/projection matrices

  1. #1
    Intern Newbie
    Join Date
    Jan 2014
    Posts
    33

    Directional light and shadow mapping view/projection matrices

    I'm having trouble implementing shadow mapping for directional lights (lights with a light direction but no defined position; such as the sun).
    I managed to get spotlights shadow mapping working in an earlier thread I made.

    The problem I have is the construction of the view and the projection matrices which boogles my mind. Here's what I use right now:

    Code :
    Mat4 viewMatrix = LookAt(Vec3(0.0f) + (directionalLight.mLightDirection * Z_FAR / 2.0f), -directionalLight.mLightDirection, Vec3(0.0f, 1.0f, 0.0f));
    Mat4 lightVP    = CreateOrthographicMatrix(-Z_FAR, Z_FAR, -Z_FAR, Z_FAR, Z_NEAR, Z_FAR) * viewMatrix;

    Z_NEAR is 0.1f and Z_FAR is 100.0f.

    My problems:

    1) For glm:rtho, I understand the first four parameters define the bounding box but does the 5th and 6th argument have to be in the same dimensions or are they constant throughout the program?
    2) When constructing the view matrix, I run into issues when the camera is far off from the center, say 150 units +X and there are objects there that needs to be shadowed. How do I specify the position properly? If I use the camera position as the position to LookAt(), the shadows will appear to move around when the camera is moving aswell...
    3) I use (directionalLight.mLightDirection * Z_FAR / 2.0f) to position the lights view far away, but it is almost too far so I need a large bounding box and so loose alot of precision... what is a more proper value to offset the lights view position with?
    4) I suppose I need the centrum point in the bounding box as the position for the lights view matrix, but how do I define a reasonable bounding box using glm:rtho? The reason I use Z_FAR in all directions is because the camera could be looking in any direction and all withing the viewing range should be shadowed, but the precision in the shadowmap is really bad and the shadows looks very pixelated.

    Any pointers to this problem?

  2. #2
    Intern Newbie
    Join Date
    Jan 2014
    Posts
    40
    Think of light's orthographic frustum as a bounding box that encloses all objects visible by the camera, plus objects not visible but potentially casting shadows. For the simplicity let's disregard the latter.
    So to find this frustum:

    - find all objects that are inside the current camera frustum
    - find minimal aa bounding box that encloses them all
    - transform corners of that bounding box to the light's space (using light's view matrix)
    - find aa bounding box in light's space of the transformed (now obb) bounding box
    - this aa bounding box is your directional light's orthographic frustum.

    Note that actual translation component in light view matrix doesn't really matter as you'll only get different Z values for the frustum but the boundaries will be the same in world space. For the convenience, when building light view matrix, you can assume the light "position" is at the center of the bounding box enclosing all visible objects.
    Last edited by nenad*; 01-27-2014 at 04:17 PM.

  3. #3
    Intern Newbie
    Join Date
    Jan 2014
    Posts
    33
    If I keep the position in the center of the box, won't the shadows be skewed due to the light being too close-up with the objects?

  4. #4
    Intern Newbie
    Join Date
    Jan 2014
    Posts
    40
    There is no position in directional light. Think of position and target vectors you pass to LookAt as representing the light direction vector:

    direction = target - positiont

    Shadows won't be skewed since you use orthographic projection to render the shadow map
    So:

    Code :
    position = centerOfBBox;
    target = position + lightDirection;
    Mat4 lightViewMatrix = LookAt(position, target, Vec3(0.0f, 1.0f, 0.0f));
    Last edited by nenad*; 01-28-2014 at 06:35 AM. Reason: imprecise info

  5. #5
    Intern Newbie
    Join Date
    Jan 2014
    Posts
    33
    Thank you, it looks better now, but I still have a problem.

    Just before the camera leaves the extent of the shadows of the models, the shadows sometimes gets wierd artifacts, like very stretched shadows, see below in pic 2; the floating sphere gets a very elongated shadow at the edge of the visibility of the shadows

    Click image for larger version. 

Name:	badshadows1.jpg 
Views:	1288 
Size:	19.6 KB 
ID:	1221Click image for larger version. 

Name:	badshadows2.jpg 
Views:	1514 
Size:	14.7 KB 
ID:	1222

    I have the view/projection like you posted;

    Code :
    Mat4 viewMatrix = LookAt(lighting.mCameraPosition, lighting.mCameraPosition + glm::normalize(directionalLight.mLightDirection), Vec3(0.0f, 1.0f, 0.0f));
    Mat4 lightVP = CreateOrthographicMatrix(lighting.mCameraPosition.x - 25.0f, lighting.mCameraPosition.x + 25.0f, lighting.mCameraPosition.y - 25.0f, lighting.mCameraPosition.y + 25.0f, lighting.mCameraPosition.z + 25.0f, lighting.mCameraPosition.z - 25.0f) * viewMatrix;

    My fragment shader looks like this, if the error is there...?

    Code :
        const std::string gDirLightFragmentShader =
        "#version 430                                                                                                                   \n \
                                                                                                                                        \n \
        layout(std140) uniform;                                                                                                         \n \
                                                                                                                                        \n \
        uniform UnifDirLight                                                                                                            \n \
        {                                                                                                                               \n \
            mat4 mVPMatrix;                                                                                                             \n \
            vec4 mLightColor;                                                                                                           \n \
            vec4 mLightDir;                                                                                                             \n \
            vec4 mGamma;                                                                                                                \n \
            vec2 mScreenSize;                                                                                                           \n \
        } UnifDirLightPass;                                                                                                             \n \
                                                                                                                                        \n \
        layout (binding = 2) uniform sampler2D unifPositionTexture;                                                                     \n \
        layout (binding = 3) uniform sampler2D unifNormalTexture;                                                                       \n \
        layout (binding = 4) uniform sampler2D unifDiffuseTexture;                                                                      \n \
        layout (binding = 6) uniform sampler2DShadow unifShadowTexture;                                                                 \n \
                                                                                                                                        \n \
        out vec4 fragColor;                                                                                                             \n \
                                                                                                                                        \n \
        void main()                                                                                                                     \n \
        {                                                                                                                               \n \
            vec2 texcoord = gl_FragCoord.xy / UnifDirLightPass.mScreenSize;                                                             \n \
                                                                                                                                        \n \
            vec3 worldPos = texture(unifPositionTexture, texcoord).xyz;                                                                 \n \
            vec3 normal   = normalize(texture(unifNormalTexture, texcoord).xyz);                                                        \n \
            vec3 diffuse  = texture(unifDiffuseTexture, texcoord).xyz;                                                                  \n \
                                                                                                                                        \n \
            vec4 lightClipPos = UnifDirLightPass.mVPMatrix * vec4(worldPos, 1.0);                                                       \n \
            vec3 projCoords   = lightClipPos.xyz / lightClipPos.w;                                                                      \n \
            projCoords.z      = projCoords.z - 0.005;                                                                                   \n \
                                                                                                                                        \n \
            float visibilty  = texture(unifShadowTexture, projCoords);                                                                  \n \
                                                                                                                                        \n \
            float angleNormal = clamp(dot(normal, UnifDirLightPass.mLightDir.xyz), 0, 1);                                               \n \
                                                                                                                                        \n \
            fragColor = vec4(diffuse, 1.0) * visibilty * angleNormal * UnifDirLightPass.mLightColor;                                    \n \
        }


    EDIT: Another issue I found is the shadows gets clipped on objects at a certain distance when moving the camera around - must be caused by the orthographic bounds somehow?
    Click image for larger version. 

Name:	badshadows3.jpg 
Views:	1139 
Size:	19.1 KB 
ID:	1223
    Last edited by TheKaiser; 01-30-2014 at 12:17 PM.

Posting Permissions

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