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

Thread: Cascade Shadow Mapping: artefacts via sampler2D array

  1. #1
    Junior Member Newbie
    Join Date
    Nov 2017
    Posts
    14

    Unhappy Cascade Shadow Mapping: artefacts via sampler2D array

    Hi, All.

    I,m trying to refactor shader for arrays instead several textures.

    I have problem with artefacts on the shadow maps border when I'm using:

    Code :
    uniform sampler2D shadowMap[3];

    instead:
    Code :
    uniform sampler2D shadowMap_0;
    uniform sampler2D shadowMap_1;
    uniform sampler2D shadowMap_2;

    there is a screenshot: Click image for larger version. 

Name:	texture array border.jpg 
Views:	28 
Size:	17.5 KB 
ID:	2558

    Have no idea where is the problem.

    Regards.
    Thanks, for ansver.
    Last edited by nimelord; 11-20-2017 at 02:13 PM.

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,515
    How are you indexing the array, and which GLSL version are you using?

    In GLSL 4.x, arrays of samplers may only be indexed with dynamically-uniform expressions (in a vertex shader the expression may only involve uniform variables, in a fragment shader it may only involve uniform variables and flat-qualified inputs).

    In prior versions, arrays of samplers may only be indexed with constant expressions (you can't even use uniform variables; the expression must be capable of being evaluated during shader compilation).

    If you try to index a sampler array with an expression which doesn't meet these constraints, the behaviour is undefined.

    If you can't satisfy these constraints, then consider using an array texture instead.

  3. #3
    Junior Member Newbie
    Join Date
    Nov 2017
    Posts
    14
    I'm not sure what do you mean.

    But I use indexing dynamically, calculating index directly in the shader, not via uniform.

    shader sample:

    Code :
    #version 400
     
    const int NUM_CASCADES = 3;
     
    uniform sampler2D dlShadowMap[NUM_CASCADES];
    uniform float cascadeFarPlanes[NUM_CASCADES];
     
    ....
     
    float calcShadow(vec4 position, int idx, vec3 normal, vec3 lightNormal) {
     
      vec3 projCoords = position.xyz;
      projCoords = projCoords * 0.5 + 0.5;
      float bias = 0.0002;
     
      float shadowFactor = 0.0;
      vec2 inc = 1.0 / textureSize(dlShadowMap[idx], 0);
     
      for(int row = -1; row <= 1; ++row) {
        for(int col = -1; col <= 1; ++col) {
          float textDepth = texture(dlShadowMap[idx], projCoords.xy).r;
          shadowFactor += projCoords.z - bias > textDepth ? 1.0 : 0.0;
        }
      }
      shadowFactor /= 9.0;
     
      if(projCoords.z > 1.0) {
        shadowFactor = 1.0;
      }
     
      return 1 - shadowFactor;
    }
     
     
    void main() {
     
      ....
     
      int idx;
      for (int i=0; i<NUM_CASCADES; i++) {
        if ( abs(mvVertexPos.z) < cascadeFarPlanes[i] ) {
          idx = i;
          break;
        }
      }
     
     
      float shadow = calcShadow(mlightviewVertexPos[idx], idx, currNomal, normalize(directionalLight.direction));
      fragColor = clamp(ambientC * vec4(ambientLight, 1) + directionalLightResult * shadow + aroundLight, 0, 1);
      float distance = length(mvVertexPos);
      fragColor = calcDistanceDiffusing(distance, fragColor, distanceDiffusing);
    }


    This is incorrect using, am i right?
    Last edited by nimelord; 11-21-2017 at 01:00 AM. Reason: grammar mistake

  4. #4
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,515
    Quote Originally Posted by nimelord View Post
    This is incorrect using, am i right?
    It's incorrect.

    In a vertex shader, the index expression can only use constants and uniforms, i.e. the index must be the same for all vertices in the same draw call.

  5. #5
    Junior Member Newbie
    Join Date
    Nov 2017
    Posts
    14
    I moved calculation of index to vertex shader from faragment one.
    And I have the same result with artefacts.

    vertex shader:

    Code :
    #version 400
     
    const int DL_NUM_CASCADES = 3;
     
    flat out int dlCascadeIndex;
     
    uniform float cascadeFarPlanes[DL_NUM_CASCADES];
     
     
    void main()
    {
    ...    
      for (int i=0; i<DL_NUM_CASCADES; i++) {
        if ( abs(mvVertexPos.z) < cascadeFarPlanes[i] ) {
          dlCascadeIndex = i;
          break;
        }
      }
    ....
    }


    fragment shader:
    Code :
    #version 400
     
    const int NUM_CASCADES = 3;
     
    flat in int dlCascadeIndex;
     
    uniform sampler2D dlShadowMap[NUM_CASCADES];
     
     
    .....
     
    textDepth = texture(dlShadowMap[dlCascadeIndex], projCoords.xy + vec2(row, col) * inc).r;
     
     
    ......


    Could you answer another one question, please: OpenGL make one vertex shader call per one frame shader call?
    Last edited by nimelord; 11-21-2017 at 10:42 AM.

  6. #6
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,515
    Quote Originally Posted by nimelord View Post
    I moved calculation of index to vertex shader from faragment one.
    And I have the same result with artefacts.
    Your updated code is valid for GLSL 4.x.

    Quote Originally Posted by nimelord View Post
    Could you answer another one question, please: OpenGL make one vertex shader call per one frame shader call?
    No. The vertex shader is invoked once per vertex (if you're using e.g. glDrawElements() and a vertex index is repeated, the vertex shader may be executed again or cached results from a previous invocation may be used). The fragment shader is invoked once per fragment. The outputs from the vertex shader are interpolated across the primitive to obtain the values fed to the fragment shader (for flat-qualified and integer variables, the value computed for one of the vertices is used for all fragments).

  7. #7
    Junior Member Newbie
    Join Date
    Nov 2017
    Posts
    14
    I can have one part of the fragment in under one shadow map and other part of fragment under second shadow map.
    That means one fragment should use different indexes, but because reasons you described it uses one.


    It seems only one solution - array texture.
    Last edited by nimelord; 11-21-2017 at 12:44 PM.

  8. #8
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,167
    Quote Originally Posted by nimelord View Post
    It seems only one solution - array texture.
    There are others (atlas, cube map, etc.), but array textures are the best solution I know of.

    By the way, when you get there, you may end up hitting artifacts on shadow map split boundaries (the shadow maps indexed by the indices referred to above). If you want the joy of figuring out the root cause yourself, don't read the rest of this message. But if not, check out this thread: Cascaded shadow map bug between splits.

  9. #9
    Junior Member Newbie
    Join Date
    Nov 2017
    Posts
    14
    Thank you, guys!

    I did it via array texture.
    Last edited by nimelord; 11-23-2017 at 02:30 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
  •