OpenGL 4 multiple shadow maps

Started by
26 comments, last by taby 1 year, 7 months ago

I have multiple lights built into the little app now. As you can see, there are multiple shadows. The thing of it is, the overlapping region where both shadows are ends up being darker than where there is only one shadow. Any ideas on how to make it so that if in either shadow, the shaded value is set to some constant?

In the shader, I am simply doing something like this:

shadow = textureProj(shadow_map, ShadowCoord);
shadow += textureProj(shadow_map2, ShadowCoord2);

Any ideas?

Advertisement

Oops, the solution is:

    float shadow1 = 1.0;
    float shadow2 = 1.0;
    
   if( ShadowCoord.z >= 0.0 )
    {
      shadow1 = textureProj(shadow_map, ShadowCoord);
    }
    
   if( ShadowCoord2.z >= 0.0 )
    {
      shadow2 = textureProj(shadow_map2, ShadowCoord2);
    }

    float shadow = 1.0;

    if(shadow1 != 1.0 || shadow2 != 1.0)
        shadow = 0.25;

I am passing in multiple shadow maps like

uniform sampler2DShadow shadow_map;
uniform sampler2DShadow shadow_map2;

Is there a way to make this into an array?

I found that I can use an array:

glActiveTexture(GL_TEXTURE4);
glUniform1i(glGetUniformLocation(shadow_map.get_program(), "shadow_maps[0]"), 4);

glActiveTexture(GL_TEXTURE5);
glUniform1i(glGetUniformLocation(shadow_map.get_program(), "shadow_maps[1]"), 5);

And in the shader:

uniform sampler2DShadow shadow_maps[2];

So, does this mean that there is a maximum number of lights? Like, I believe that my computer can do 32 textures at a time, but I have to leave some for the other parts of the code. So, is it reasonable to limit the number of lights to like 24? Or is there some way around this limitation?

I figured it out. Start max contribution to 0. Then loop through the lights and shadow maps and set the max contribution if larger than the max contribution.

taby said:
Then loop through the lights and shadow maps

Can you access array textures with [index] in shader code?
And does it overcome the max 32 limit, so texture array counts as only ‘one’ texture?

taby said:
does this mean that there is a maximum number of lights

glGetIntegerv(GL_MAX_TEXTURE_UNITS, &iUnits);

i recommend not to exceed 4, you already did

joej… on my machine I can have 32 active textures. There is likely a way to do it with one gigantic shadow map, but I don’t know how. So in my game, I allow for up to 24 lights.

The working fragment shader is:

#version 430 core
out vec4 FragColor;

in VS_OUT {
    vec3 FragPos;
    vec3 Normal;
    vec2 TexCoords;
    vec3 mvPosition;
} fs_in;


const int max_num_lights = 2;
uniform samplerCube depthMaps[max_num_lights];


uniform sampler2D diffuseTexture;

uniform vec3 lightPositions[max_num_lights];

uniform vec3 viewPos;

uniform float far_plane;
uniform int shadows = 1;


vec3 LightIntensity = vec3(1.0, 1.0, 1.0);
    vec3 MaterialKd = vec3(1.0, 1.0, 1.0);
    vec3 MaterialKs = vec3(1.0, 0.5, 0.0);
vec3 MaterialKa = vec3(0.0, 0.025, 0.075);
float MaterialShininess = 10.0;


vec3 phongModelDiffAndSpec(bool do_specular, vec3 lp)
{
    vec3 n = fs_in.Normal;
    vec3 s_light1 = normalize(vec3(lp.xyz) - fs_in.mvPosition);

    vec3 v = normalize(-fs_in.mvPosition.xyz);
    vec3 r_light1 = reflect( -s_light1, n );

    float sDotN_light1 = max( dot(s_light1,n), 0.0 );

    vec3 diffuse_light1 = LightIntensity * texture(diffuseTexture, fs_in.TexCoords).rgb * sDotN_light1;

    vec3 spec_light1 = vec3(0.0);

    if( sDotN_light1 > 0.0 )
    {
        spec_light1.x = MaterialKs.x * pow( max( dot(r_light1,v), 0.0 ), MaterialShininess );
        spec_light1.y = MaterialKs.y * pow( max( dot(r_light1,v), 0.0 ), MaterialShininess );
        spec_light1.z = MaterialKs.z * pow( max( dot(r_light1,v), 0.0 ), MaterialShininess );
    }

    vec3 n2 = fs_in.Normal;

    vec3 s2_light1 = normalize(vec3(-lp) - fs_in.mvPosition);

    vec3 v2 = normalize(-fs_in.mvPosition.xyz);
    
    vec3 r2_light1 = reflect( -s2_light1, n2 );
    
    
    
    float sDotN2_light1 = max( dot(s2_light1,n2)*0.5f, 0.0 );




    vec3 diffuse2_light1 = LightIntensity*0.25 * MaterialKa * sDotN2_light1;



    float k_light1 = (1.0 - sDotN_light1)/2.0;



    vec3 ret_light1 = diffuse_light1 + diffuse2_light1 + MaterialKa*k_light1;

    if(do_specular)
    {
        ret_light1 = ret_light1 + spec_light1;
    }

    return (ret_light1);// + ret_light2);///2.0;
}


float get_shadow(vec3 lp, samplerCube dmap)
{
    float shadow = 0.0;
    
    // get vector between fragment position and light position
    vec3 fragToLight = fs_in.FragPos - lp;
    // ise the fragment to light vector to sample from the depth map    
    float closestDepth = texture(dmap, fragToLight).r;
    // it is currently in linear range between [0,1], let's re-transform it back to original depth value
    closestDepth *= far_plane;
    // now get current linear depth as the length between the fragment and light position
    float currentDepth = length(fragToLight);
    // test for shadows
    float bias = 0.05; // we use a much larger bias since depth is now in [near_plane, far_plane] range
     shadow = currentDepth -  bias > closestDepth ? 1.0 : 0.0;        
     
     shadow = 1 - shadow;
    
       return shadow;

     }



void main()
{
        float brightest_contribution = 0.0;

       for(int i = 0; i < max_num_lights; i++)
        {
            float s = get_shadow(lightPositions[i], depthMaps[i]);
            
            if(s > brightest_contribution)
                brightest_contribution = s;
        }

         vec3 diffAndSpec = vec3(0, 0, 0);

    if(brightest_contribution == 1.0)
    {
        for(int i = 0; i < max_num_lights; i++)
            diffAndSpec += phongModelDiffAndSpec(true, lightPositions[i]);
  
        FragColor = vec4(diffAndSpec, 1.0);// + vec4(diffAndSpec * shadow + MaterialKa*(1.0 - shadow), 1.0);
    }
    else
    {
        for(int i = 0; i < max_num_lights; i++)
            diffAndSpec += phongModelDiffAndSpec(false, lightPositions[i]);

        FragColor = vec4(diffAndSpec * brightest_contribution + MaterialKa*(1.0 - brightest_contribution), 1.0) + vec4(diffAndSpec, 1.0) + vec4(diffAndSpec * brightest_contribution + MaterialKa*(1.0 - brightest_contribution), 1.0);
        FragColor /= 3;
    }

    FragColor = pow( FragColor, vec4(1.0 / 2.2) );


    return;
}

float s = get_shadow(lightPositions[i], depthMaps[i]);

That's nice to see. (Never used texture arrays.)

taby said:
So in my game, I allow for up to 24 lights.

Let me know what perf you get for 24 shadowed lights in a fairly complex scene… sounds very ambitious ; )

Reminds me on this paper, taking every optimization one could think of: http://www.cse.chalmers.se/~uffe/ClusteredWithShadows.pdf

This topic is closed to new replies.

Advertisement