多个灯光阴影映射

时间:2014-10-18 17:36:28

标签: c++ opengl glsl lighting shadow-mapping

问题是我将几个灯光传递到着色器,但它只显示第一个阴影。 灯光也适用于没有看到阴影的灯光。 我检查了阴影贴图并正确传递了它们。 片段着色器:

#version 420 compatibility
#define MAX_LIGHTS 8
struct lightSource
{
  vec4 position;
  vec4 diffuse;
  vec4 specular;
  float constantAttenuation, linearAttenuation, quadraticAttenuation;
  float spotCutoff, spotExponent, intensity;
  vec3 spotDirection;
  sampler2D TexShadow;
  samplerCube TexShadowPoint;
}; 
struct material
{
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  float shininess;
};

uniform material frontMaterial;
uniform lightSource lights[MAX_LIGHTS];
uniform int numberOfLights;
uniform vec4 scene_ambient;
uniform mat4 inversedViewMatrix;
uniform sampler2D Tex;
uniform sampler2D TexNorm;

in vec4 position;  // position of the vertex (and fragment) in world space
in vec3 varyingNormalDirection;  // surface normal vector in world space
in vec2 ex_UV;
in vec4 ShadowCoords[MAX_LIGHTS];

vec2 poissonDisk[16] = vec2[]( 
   vec2( -0.94201624, -0.39906216 ), vec2( 0.94558609, -0.76890725 ), 
   vec2( -0.094184101, -0.92938870 ), vec2( 0.34495938, 0.29387760 ), 
   vec2( -0.91588581, 0.45771432 ), vec2( -0.81544232, -0.87912464 ), 
   vec2( -0.38277543, 0.27676845 ), vec2( 0.97484398, 0.75648379 ), 
   vec2( 0.44323325, -0.97511554 ), vec2( 0.53742981, -0.47373420 ), 
   vec2( -0.26496911, -0.41893023 ), vec2( 0.79197514, 0.19090188 ), 
   vec2( -0.24188840, 0.99706507 ), vec2( -0.81409955, 0.91437590 ), 
   vec2( 0.19984126, 0.78641367 ), vec2( 0.14383161, -0.14100790 ) 
);
float rand(vec2 co)
{
  return fract(sin(dot(co, vec2(12.9898, 78.233)) * 43758.5453));
}
float linstep(float low, float high, float v)
{
    return clamp((v-low)/(high-low), 0.0, 1.0);
}
float VSM(sampler2D depths, vec2 uv, float compare)
{
    vec2 moments = texture2D(depths, uv).xy;
    float p = smoothstep(compare - 0.02, compare, moments.x);
    float variance = max(moments.y - moments.x*moments.x, -0.001);
    float d = compare - moments.x;
    float p_max;
    p_max = linstep(0.6, 1.0, variance / (variance + d*d));
    return clamp(max(p, p_max), 0.0, 1.0) / 2;
}
void main(void)
{
    vec3 normalDirection;
    //sample the normal map and covert from 0:1 range to -1:1 range
    if (texture2D(TexNorm, ex_UV).rgb != vec3(0.0, 0.0, 0.0))
    {
        vec3 mapped_Normals = texture2D(TexNorm, ex_UV).rgb * 2.0 - 1.0;
        normalDirection = normalize(mapped_Normals); //normal mapped normals
    }
    else
        normalDirection = normalize(varyingNormalDirection);
    vec4 texColor = texture2D(Tex, ex_UV);// usual processing of texture coordinates

    vec3 viewDirection = normalize(vec3(inversedViewMatrix * vec4(0.0, 0.0, 0.0, 1.0) -     position));
    vec3 lightDirection;
    float attenuation;
    //initialize total lighting with ambient lighting
    vec3 totalAmbientDiffuse = vec3(scene_ambient) * vec3(frontMaterial.ambient);
    vec3 totalSpecular;
    for (int index = 0; index < numberOfLights; index++) // for all light sources
    {
        float Visibility;
        if (lights[index].position.w == 0.0) // directional light
        {
            attenuation = 1.0; // no attenuation
            lightDirection = normalize(vec3(lights[index].position));
            //int num = int(rand(position.xyz) * 16);
            Visibility = VSM(lights[index].TexShadow, ShadowCoords[index].xy + poissonDisk[int(rand(position.xy + vec2(position.z,-position.z)) * 16)] /2000, ShadowCoords[index].z);
        }
        else // point light or spotlight (or other kind of light) 
        {
            vec3 positionToLightSource = vec3(lights[index].position - position);
            float Distance = length(positionToLightSource);
            lightDirection = normalize(positionToLightSource);
            attenuation = 1.0 / (lights[index].constantAttenuation + lights[index].linearAttenuation * Distance + lights[index].quadraticAttenuation * Distance * Distance);
            if (lights[index].spotCutoff <= 90.0) // spotlight
            {
                Visibility = VSM(lights[index].TexShadow, ShadowCoords[index].xy / ShadowCoords[index].w + poissonDisk[int(rand(position.xy + vec2(position.z,-position.z)) * 16)] / 700, ShadowCoords[index].z / ShadowCoords[index].w);
                float clampedCosine = max(0.0, dot(-lightDirection, normalize(lights[index].spotDirection)));
                if (clampedCosine < cos(radians(lights[index].spotCutoff))) // outside of spotlight cone
                {
                    attenuation = 0.0;
                }
                else
                {
                    attenuation = attenuation * pow(clampedCosine, lights[index].spotExponent);   
                }
            }
            else // point light
            {
                //point light shadow calculations
            }
        }
        vec3 diffuseReflection = attenuation * vec3(lights[index].diffuse) *     vec3(frontMaterial.diffuse) * max(0.0, dot(normalDirection, lightDirection));
        vec3 specularReflection;
        if (dot(normalDirection, lightDirection) < 0.0) // light source on the wrong side
        {
            specularReflection = vec3(0.0, 0.0, 0.0); // no specular reflection
        }
        else // light source on the right side
        {
            specularReflection = attenuation * vec3(lights[index].specular) * vec3(frontMaterial.specular) 
            * pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), frontMaterial.shininess);
        }
        totalAmbientDiffuse += diffuseReflection * lights[index].intensity * Visibility;
        totalSpecular += specularReflection * lights[index].intensity * Visibility;
    }
    gl_FragColor = vec4(totalAmbientDiffuse, 1.0) * texColor + vec4(totalSpecular, 1.0);
}

0 个答案:

没有答案