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 10 of 17

Thread: GLSL - cube shadows - projecting

Hybrid View

  1. #1
    Junior Member Newbie
    Join Date
    Mar 2011
    Posts
    13

    GLSL - cube shadows - projecting

    Before i ask, i would like to apologize for starting here with a question.

    The thing is that i couldn't find answer to my problem anywhere, and decided to post it here finally, to speak to gurus.

    Here is what i am trying to achieve:

    Omni directional shadow, by using FBO and GL_TEXTURE_CUBE_MAP with GL_DEPTH_ATTACHMENT.

    So far, all works fine - render to all 6 faces of the cube map within FBO looks promising, the only thing left is to project that within the shader.

    Now, to visualize what exactly is happening:

    - here is the screen shot from the level editor, you can see a single omni light there that is the shadow-caster.



    - here is the scene rendered with light (without shadow)



    - here is the gdebugger cube map dump





    With all that, i am passing the cube map to the fragment shader using:

    uniform samplerCubeShadow shadowMap;

    I sample it in fragment with:

    float SHADOW=shadowCube( shadowMap, normalize(lightToSurface) );
    gl_FragColor=light(0)*SHADOW;
    where

    lightToSurface = ((gl_ModelViewMatrix * gl_Vertex).xyz-gl_LightSource[0].position.xyz) / gl_LightSource[0].spotExponent;

    spotExponent - is the radius, i pass the Omni light radius with that to the shader.


    This produces :





    The question is:
    How to project the shadow by using samplerCubeShadow in GLSL ?


    Many thanks for any help with this, I've spent days trying to figure that out, no success.. What's interesting is that even google does not pop up any example .. is this samplerCubeShadow something that is rarely used, or not used at all?

  2. #2
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948

    Re: GLSL - cube shadows - projecting

    float SHADOW=shadowCube( shadowMap, normalize(lightToSurface) );
    First of all, where does "shadowCube" come from? It's not part of the unextended standard GLSL (any version, even pre-1.30). So what extension provides it? Have you activated that extension?

    Second, what values do you expect "shadowCube" to return? If it's a float on the [0, 1] range that is proportional to the number of samples that pass the depth comparison test, then you seem to have forgotten a key ingredient:

    The depth comparison reference value.

    I can't say how "shadowCube" works, but in 1.30 and above, "texture" when given a "samplerCubeShadow" sampler, takes a vec4, not a vec3. The fourth component is the reference value for the depth comparison. That is, the depth of this fragment, relative to the light source in question.

  3. #3
    Junior Member Newbie
    Join Date
    Mar 2011
    Posts
    13

    Re: GLSL - cube shadows - projecting

    Alfonse Reinheart,
    you are totally right, the 'shadowCube' was something i was told when i was speaking to few guys around.

    And seriously I'll try hard to go back with the histories and find out who and how was trying to use it.

    *update* found it,

    http://www.opengl.org/registry/specs...pu_shader4.txt


    OK, let's switch to 'texture' when using samplerCubeShadow.
    How should that be used then, can you help me out _please_?

    I have totally lost the plot now, what should go in vec4 for texture and what is returned back ?

    Thank you v.much.

  4. #4
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,124

    Re: GLSL - cube shadows - projecting

    Quote Originally Posted by donmof
    shadowCube' was something i was told when i was speaking to few guys around.
    Yes, I believe that's the name of the texture access function in GLSL 1.2 and earlier (more on that below). samplerCubeShadow is the name of the sampler type.

    OK, let's switch to 'texture' when using samplerCubeShadow.
    How should that be used then, can you help me out _please_?

    How to project the shadow by using samplerCubeShadow in GLSL ?

    I have totally lost the plot now, what should go in vec4 for texture and what is returned back ?
    As EXT_gpu_shader4 indicates, coord.stp (i.e. coord.xyz) is the direction vector (from the point light to the fragment you are trying to evaluate shadows for). And coord.q is the R value (i.e. depth value to compare against).

    Typically with hardware shadow lookups like this, the R value is the lights' window-space depth value (0..1) associated with the fragment you are computing shadows for. However, I'm a little unsure about with cube maps because there are 6 distinct light frusta/projections. I'll look around a bit. My guess is you use the direction vector (coord.stp) to figure out which face of the cubemap you're on and use its camera-eye-to-light transform to back-project into the right light space yielding coord.q (the depth value of the fragment in the light's window-space).

    When you do a shadow lookup, the hardware does the depth compares and returns back to you a "visibility" term in 0..1, where 0 = no visibility (i.e. totally in shadow) and 1 = 100% visibility (i.e. not in shadow at all).

    If you set NEAREST filtering on the depth texture you bind to the shadow sampler, then you'll always get only 0 or 1. However if you enable LINEAR filtering, then this enables PCF shadow lookups, which means the hardware may do multiple shadow lookups, compares on each, and blend the results, giving you 0, 1, or some number in between. With LUMINANCE DEPTH_TEXTURE_MODE, this value is stuffed in .r, .g, and .b of the return value, so you can grab it from any of these.

    By the way, this presumes you've got your texture attributes set up as follows (typical for shadow map lookups):

    Code :
    glTexParameteri( target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );
    glTexParameteri( target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
    glTexParameteri( target, GL_DEPTH_TEXTURE_MODE  , GL_LUMINANCE );
    glTexParameteri( target, GL_TEXTURE_MIN_FILTER  , GL_LINEAR );
    glTexParameteri( target, GL_TEXTURE_MAG_FILTER  , GL_LINEAR );

    Also note that pre-GLSL 1.3, your texture access function should be shadowCube (or shadowCubeProj -- more likely with point light source shadows which are perspective projection). Post-GLSL 1.3 it'd be texture (or textureProj) -- in GLSL 1.3 they stopped having different names for each type of sampler and just overloaded the texture access function names.

    However in both cases, AFAIK, the sampler type you should use is samplerCubeShadow (though it's unclear whether GLSL 1.2 supported this). The shadow on the end of the name requires: 1) that you bind a depth texture to it, 2) depth compare (GL_TEXTURE_COMPARE_MODE) must be enabled on the texture.

    That said, I haven't personally coded depth cubemaps yet so there may be some errors here.

  5. #5
    Advanced Member Frequent Contributor arekkusu's Avatar
    Join Date
    Nov 2003
    Posts
    761

    Re: GLSL - cube shadows - projecting

    Cube + Proj is not valid. Projection by q doesn't work for cubemaps.

    Cube translates an .str vector to a face + .st offset; for non-shadow lookups q would be the length of the vector which is meaningless. For shadow, q is actually the reference value.

    SamplerCubeShadow is not supported in GLSL 1.20 unless you enable GL_EXT_gpu_shader4.

  6. #6
    Junior Member Newbie
    Join Date
    Mar 2011
    Posts
    13

    Re: GLSL - cube shadows - projecting

    Dark Photon:

    Thank you for a great introduction into this, of course my texture is set up as follows, so it meets the requirements.

    glGenTextures(1, &tDepthCubeMap);
    glBindTexture(GL_TEXTURE_CUBE_MAP, tDepthCubeMap);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_DEPTH_TEXTURE_MODE , GL_LUMINANCE );
    glTexParameterf( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );
    glTexParameterf( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

    for (int face = 0; face < 6; face++)
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_DEPTH_COMPONENT32F , 512, 512, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);


    My guess is you use the direction vector (coord.stp) to figure out which face of the cubemap you're on and use its camera-eye-to-light transform to back-project into the right light space yielding coord.q (the depth value of the fragment in the light's window-space).
    That would mean, something like :

    uniform samplerCubeShadow shadowMap;
    ...
    float visibility=texture( shadowMap, lightToSurface );
    where

    ...
    lightToSurface=vec4(gl_LightSource[0].position-(gl_ModelViewMatrix * gl_Vertex));
    That lightToSurface when passed to texture(...) should lookup the correct face of the cube, what is exactly that vec4's 4th component (.q) - how do i calculate it ?



    Thanks to all of you guys, hopefully we can get that sorted out..


    *update*

    I made a small test here,
    this is the actual light setup:




    The depth map




    And the shader's are as follows:

    [vertex shader]
    //made it vec3 - frag recreates it as vec4
    varying vec3 lightToSurface;
    vec3 vertexPos = vec3(gl_ModelViewMatrix * gl_Vertex);
    lightToSurface = (vertexPos-gl_LightSource[0].position) / gl_LightSource[0].spotExponent;
    [fragment shader]
    vec4 lts=vec4(lightToSurface.x,lightToSurface.y,lightTo Surface.z,1);
    float cDepth=texture( shadowMap, normalize(lts));
    gl_FragColor=light(0) * cDepth;
    '1' in the vector.w results:




    vec4 lts=vec4(lightToSurface.x,lightToSurface.y,lightTo Surface.z,3);
    float cDepth=texture( shadowMap, normalize(lts));
    gl_FragColor=light(0) * cDepth;
    '3' results




    Of course what is strange too is that the 'shadow' or whatever it is there 'rotates' to camera view.



  7. #7
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,124

    Re: GLSL - cube shadows - projecting

    Quote Originally Posted by arekkusu
    Cube + Proj is not valid. Projection by q doesn't work for cubemaps.

    Cube translates an .str vector to a face + .st offset; for non-shadow lookups q would be the length of the vector which is meaningless. For shadow, q is actually the reference value.
    Good point. I wasn't thinking. With shadowCubeProj/textureProj on a samplerCubeShadow, we'd be out of vec4 texcoord components to play with, so there's no room for .xyzw and the reference value (5 values).

    Also, googling around looks like most folks just use samplerCube and textureCube/texture (i.e. straight texture lookup; no hardware depth comparison) to sample cube depth maps for point light shadows for some reason. They don't get the free PCF doing it that way, so I'm not sure why, yet.

Posting Permissions

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