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;
}
for-loopのコメントを外して、影を消してしまいます。ループ内のロジックを削除しても、これを試しましたが、影はまだ表示されません。
ここにいくつかの追加情報があります。MacOS 10.11.6でXCodeを実行しています。私はコンパイルした後とリンクした後にシェイダーをチェックします。エラーは表示されません。
なぜこのようなことが起こっていますか?私はすべてを試して、私はアイデアのうち、助けてください!
すべてのユニフォームは、実行時に場所によって正しく照会されますか? 2番目のループのコメントを解除すると、 'gNumPointLights'と' gPointLights [...] 'の状態が非アクティブからアクティブに変更され、他のユニフォームに割り当てられた場所がジャンプする可能性があります。私の直感は、ユニフォーム配列の場所(特に、 'struct'の配列が動作する方法)について、あなたが悪い仮定をしていることを示しています。あなたは構造体の個々のフィールドの場所を照会していますか? –
私はこう考えています: "gPointLights [%d] .Base.Color"という文字列で、%dは0,1,2,3に置き換えられます。スポットライトは完全に素晴らしいです(シェイダーの動作を変更しないでそれを削除または残して)。 – ChaoSXDemon