2016-10-03 3 views
2

私は指向性、ポイント、スポットライトを計算するフラグメントシェーダーを持っています。シャドウマップなしでは、これはうまく動作します。奇妙なのは、シャドウマップ(sampler2D)を追加した後に、どのようにシャドーがシャドーするかという点です。ここに私のフラグメントシェーダだ:と影 - ループのためにコメントアウト(詳細については、コメントを表示するために下へ進んでください)GLSL 330ポイントライトとシャドウマップwierdness

#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; 
} 

は大丈夫です! correct rendering with shadows

for-loopのコメントを外して、影を消してしまいます。ループ内のロジックを削除しても、これを試しましたが、影はまだ表示されません。 shadows gone with the for-loop uncommented

ここにいくつかの追加情報があります。MacOS 10.11.6でXCodeを実行しています。私はコンパイルした後とリンクした後にシェイダーをチェックします。エラーは表示されません。

なぜこのようなことが起こっていますか?私はすべてを試して、私はアイデアのうち、助けてください!

+0

すべてのユニフォームは、実行時に場所によって正しく照会されますか? 2番目のループのコメントを解除すると、 'gNumPointLights'と' gPointLights [...] 'の状態が非アクティブからアクティブに変更され、他のユニフォームに割り当てられた場所がジャンプする可能性があります。私の直感は、ユニフォーム配列の場所(特に、 'struct'の配列が動作する方法)について、あなたが悪い仮定をしていることを示しています。あなたは構造体の個々のフィールドの場所を照会していますか? –

+0

私はこう考えています: "gPointLights [%d] .Base.Color"という文字列で、%dは0,1,2,3に置き換えられます。スポットライトは完全に素晴らしいです(シェイダーの動作を変更しないでそれを削除または残して)。 – ChaoSXDemon

答えて

0

一部のデバッグ後、使用されていない一様な変数が問題を引き起こしていることが判明しました。