2016-10-03 29 views
2

我有一个片段着色器,用于计算方向,点和点光源。没有阴影贴图,这工作正常。奇怪的是,在添加阴影贴图(sampler2D)之后,点亮一些如何跺跺阴影。这里是我的片段着色器:(跳到底部详见注释)GLSL 330点光和阴影贴图粗糙

#version 330 core 

const int MAX_POINT_LIGHTS = 4; 
const int MAX_SPOT_LIGHTS = 4; 

in vec2 TexCoord0; 
in vec3 WorldNormal0; 
in vec3 WorldPos0; 
in vec4 LightSpacePos0; 
in vec3 Tangent0; 

out vec4 FragmentColor; 

struct BaseLight 
{ 
    vec3 Color; 
    float AmbientIntensity; 
    float DiffuseIntensity; 
}; 

struct DirectionalLight 
{ 
    BaseLight Base; 
    vec3 Direction; 
}; 

struct Attenuation 
{ 
    float Constant; 
    float Linear; 
    float Exp; 
}; 

struct PointLight 
{ 
    BaseLight Base; 
    vec3 Position; 
    Attenuation Atten; 
}; 

struct SpotLight 
{ 
    PointLight Base; 
    vec3 Direction; 
    float Cutoff; 
}; 

uniform int gNumPointLights; 
uniform int gNumSpotLights; 
uniform DirectionalLight gDirectionalLight; 
uniform PointLight gPointLights[MAX_POINT_LIGHTS]; 
uniform SpotLight gSpotLights[MAX_SPOT_LIGHTS]; 
uniform sampler2D gTextureSampler0; //unit 0 
uniform sampler2D gShadowMap;  //unit 1 
uniform vec3 gEyeWorldPos; 
uniform float gMatSpecularIntensity; 
uniform float gSpecularPower; 

float CalculateShadowFactor(vec4 light_space_pos) 
{ 
    //perspective divide 
    vec3 projected_coords = light_space_pos.xyz/light_space_pos.w; 
    //map [-1, 1] to [0, 1] 
    vec2 uv_coords; 
    uv_coords.x = 0.5 * projected_coords.x + 0.5; 
    uv_coords.y = 0.5 * projected_coords.y + 0.5; 
    float z = 0.5 * projected_coords.z + 0.5; 
    float depth = texture(gShadowMap, uv_coords).x; 
    if (depth < z - 0.0005) 
    { 
     return 0.5; //in shadow 
    } 
    else 
    { 
     return 1.0; 
    } 
} 

vec4 CalculateLightInternal(BaseLight light, vec3 direction, vec3 normal) 
{ 
    vec4 ambient_color = vec4(light.Color * light.AmbientIntensity, 1.0f); 
    float diffuse_factor = dot(normal, -direction); 

    vec4 diffuse_color = vec4(0, 0, 0, 0); 
    vec4 specular_color = vec4(0, 0, 0, 0); 

    if (diffuse_factor > 0) 
    { 
     diffuse_color = vec4(light.Color * light.DiffuseIntensity * diffuse_factor, 1.0f); 
     vec3 vertex_to_eye = normalize(gEyeWorldPos - WorldPos0); 
     vec3 light_reflect = normalize(reflect(direction, normal)); 
     float specular_factor = dot(vertex_to_eye, light_reflect); 
     if (specular_factor > 0) 
     { 
      specular_factor = pow(specular_factor, gSpecularPower); 
      specular_color = vec4(light.Color * gMatSpecularIntensity * specular_factor, 1.0f); 
     } 
    } 

    return ambient_color + diffuse_color + specular_color; 
} 

vec4 CalculateDirectionalLight(vec3 normal) 
{ 
    return CalculateLightInternal(gDirectionalLight.Base, gDirectionalLight.Direction, normal); 
} 

vec4 CalculatePointLight(PointLight light, vec3 normal) 
{ 
    vec3 light_direction = WorldPos0 - light.Position; 
    float dist = length(light_direction); 
    light_direction = normalize(light_direction); 

    vec4 color = CalculateLightInternal(light.Base, light_direction, normal); 
    float inv_attenuation = 1.0/(light.Atten.Constant + light.Atten.Linear * dist + light.Atten.Exp * dist * dist); 

    return color * inv_attenuation; 
} 

vec4 CalculateSpotLight(SpotLight light, vec3 normal) 
{ 
    vec3 light_to_pixel = normalize(WorldPos0 - light.Base.Position); 
    float spot_factor = dot(light_to_pixel, light.Direction); 

    if (spot_factor > light.Cutoff) 
    { 
     vec4 color = CalculatePointLight(light.Base, normal); 
     return color * (1.0 - (1.0 - spot_factor) * 1.0/(1.0 - light.Cutoff)); //remaps to [0,1] from cosine value so that it's a smooth fall-off 
    } 
    else 
    { 
     return vec4(0,0,0,0); 
    } 
} 

void main() 
{ 
    float shadow_factor = CalculateShadowFactor(LightSpacePos0); 
    vec4 texture_color = texture(gTextureSampler0, TexCoord0); 
    vec3 pixel_normal = normalize(WorldNormal0); 
    vec4 total_light = CalculateDirectionalLight(pixel_normal); 

    for (int i = 0; i < gNumSpotLights; ++i) 
    { 
     total_light += CalculateSpotLight(gSpotLights[i], pixel_normal); 
    } 

    //If uncomment the for-loop below, the shadow disappears ... 
    //I have tried even setting gNumPointLights to 0 and some how 
    //it still "kills" the shadow ... 
    //I also tried changing the logic to total_light += vec4(0); 
    //magically this still kills it. 
    /* 
    for (int i = 0; i < gNumPointLights; ++i) 
    { 
     total_light += CalculatePointLight(gPointLights[i], pixel_normal); 
    } 
    */ 

    FragmentColor = texture_color * total_light * shadow_factor; 
} 

注释掉的for循环和阴影都很好! correct rendering with shadows

取消注释for循环,阴影消失,没有任何其他修改。我甚至在循环内部的逻辑被移除并且阴影仍然不会显示的情况下尝试了这一点。 shadows gone with the for-loop uncommented

下面是一些额外的信息:我在Mac OS 10.11.6上用XCode运行它。我在编译后和链接后检查我的着色器。没有显示错误。

那么为什么会发生这种情况呢?我尝试了一切,我的想法出来了,请帮助!

+0

都是你的制服正确地定位在运行时查询?取消注释第二个循环会将gNumPointLights和gPointLights的状态从非活动状态变为活动状态,并可能会混杂分配给其他制服的位置。我的直觉告诉我,你对统一阵列位置做了一个错误的假设(特别是'struct'数组的工作方式)。你是否在查询struct的各个字段的位置? –

+0

我相信是这样,他们是由一个通过查询字符串之一:“gPointLights [%d] .Base.Color”,其中%d将与0,1,2和3所取代什么奇怪的是,for循环的聚光灯是完全正常的(移除它或将其留在不会改变着色器的行为)。 – ChaoSXDemon

回答

0

经过一番调试后,事实证明是未使用的统一变量搞乱了事情。