2015-06-15 113 views
2

我一直在關注OGLDev(part 1,part 2)陰影貼圖的兩部分教程,現在已經有幾天了,我幾乎已經完成了它的實現。聚光燈與陰影變得像方形一樣

我的問題是,當我啓用陰影貼圖時,出現陰影的照明區域顯示爲「strip」,我不確定這是否適用於教程。

也許圖像可以幫助解釋我的問題。 enter image description here

但是陰影功能: enter image description here

我聚光燈頂點着色器:

#version 330 

in vec2 textureCoordinate; 
in vec4 vertex; 

uniform mat4 mMatrix; 
uniform mat4 pMatrix; 
uniform mat4 vMatrix; 
uniform mat4 lightV; 
uniform mat4 lightP; 
uniform vec3 normal; 
uniform vec3 eye; 

out vec2 TexCoord0; 
out vec4 LightSpacePos; 
out vec3 Normal0; 
out vec3 WorldPos0; 
out vec3 EyePos; 

void main() 
{ 
    EyePos = eye; 
    TexCoord0 = textureCoordinate; 
    WorldPos0 = (mMatrix * vertex).xyz; 
    Normal0 = (mMatrix * vec4(normal, 0.0)).xyz; 

    mat4 lightMVP = lightP * inverse(lightV) * mMatrix; 
    LightSpacePos = lightMVP * vertex; 

    mat4 worldMVP = pMatrix * vMatrix * mMatrix; 
    gl_Position = worldMVP * vertex; 
} 

和片段着色器:

#version 330 

struct BaseLight 
{ 
    vec4 color; 
    float intensity; 
}; 

struct Attenuation 
{ 
    float constant; 
    float linear; 
    float exponent; 
}; 

struct PointLight 
{ 
    BaseLight base; 
    Attenuation atten; 
    vec3 position; 
    float range; 
}; 

struct SpotLight 
{ 
    struct PointLight base; 
    vec3 direction; 
    float cutoff; 
}; 

in vec2 TexCoord0; 
in vec3 WorldPos0; 
in vec3 EyePos; 
in vec4 LightSpacePos; 
out vec4 fragColor;   
uniform sampler2D sampler;       
uniform sampler2D shadowMap;        

in vec3 Normal0; 
uniform float specularIntensity; 
uniform float specularPower; 
uniform SpotLight spotLight; 

float CalcShadowFactor(vec4 LightSpacePos)             
{                       
    vec3 ProjCoords = LightSpacePos.xyz/LightSpacePos.w;         
    vec2 UVCoords;                   
    UVCoords.x = 0.5 * ProjCoords.x + 0.5;             
    UVCoords.y = 0.5 * ProjCoords.y + 0.5;             
    float z = 0.5 * ProjCoords.z + 0.5;              
    float Depth = texture(shadowMap, UVCoords).x;           
    if (Depth < z + 0.00001)                 
     return 0.5;                   
    else                      
     return 1.0;                   
} 

vec4 CalcLightInternal(BaseLight Light, vec3 LightDirection, vec3 Normal, float ShadowFactor)             
{                       
    vec4 AmbientColor = Light.color * Light.intensity;     
    float DiffuseFactor = dot(Normal, -LightDirection);          

    vec4 DiffuseColor = vec4(0, 0, 0, 0);             
    vec4 SpecularColor = vec4(0, 0, 0, 0);             

    if (DiffuseFactor > 0) {                 
     DiffuseColor = Light.color * Light.intensity * DiffuseFactor;  

     vec3 VertexToEye = normalize(EyePos - WorldPos0);        
     vec3 LightReflect = normalize(reflect(LightDirection, Normal));      
     float SpecularFactor = dot(VertexToEye, LightReflect);        
     SpecularFactor = pow(SpecularFactor, specularPower);        
     if (SpecularFactor > 0) {               
      SpecularColor = Light.color * specularIntensity * SpecularFactor;       
     }                     
    }                      

    return (AmbientColor + ShadowFactor * (DiffuseColor + SpecularColor));     
} 

vec4 CalcPointLight(PointLight l, vec3 Normal, vec4 LightSpacePos)     
{                       
    vec3 LightDirection = WorldPos0 - l.position;           
    float Distance = length(LightDirection);             
    LightDirection = normalize(LightDirection);            
    float ShadowFactor = CalcShadowFactor(LightSpacePos);         

    vec4 Color = CalcLightInternal(l.base, LightDirection, Normal, ShadowFactor);   
    float Attenuation = l.atten.constant +             
         l.atten.linear * Distance +           
         l.atten.exponent * Distance * Distance;         

    return Color/Attenuation;                
} 

vec4 CalcSpotLight(SpotLight l, vec3 Normal, vec4 LightSpacePos)      
{                       
    vec3 LightToPixel = normalize(WorldPos0 - l.base.position);        
    float SpotFactor = dot(LightToPixel, l.direction);          

    if (SpotFactor > l.cutoff) {                
     vec4 Color = CalcPointLight(l.base, Normal, LightSpacePos);       
     return Color * (1.0 - (1.0 - SpotFactor) * 1.0/(1.0 - l.cutoff));     
    }                      
    else {                     
     return vec4(0,0,0,0);                
    }                      
} 

void main(void) 
{  
    fragColor = texture2D(sampler, TexCoord0.xy) * CalcSpotLight(spotLight, normalize(Normal0), LightSpacePos); 
} 

回答

2

此舉意。由於您的陰影貼圖覆蓋了太空中的金字塔狀區域,因此您的聚光燈錐體可能會被遮擋。發生這種情況的原因是,如果您渲染的是陰影相機視圖之外的內容,則會被視爲無法點亮。因此,陰影相機的視圖金字塔將可見。

enter image description here
src

爲了解決這個問題,你有2個選項

1:充分利用陰影貼圖相機的視野更大,從而陰影相機的金字塔比你的聚光燈的圓錐體寬

2:更改計算陰影的方式在越界區域。目前,當您對陰影貼圖進行採樣時,如果它在陰影紋理之外,則在其上應用陰影。如果你改變這個,那麼如果一些超出陰影紋理的東西你認爲它已經消失,這個問題就會消失。

編輯: 我推薦第二個選項。一種用於該解決方案可能是: 插入以下行FragmentShader :: CalcShadowFactor(),就在float Depth = ...部分之前

if (UVCoords.x < 0.0 || UVCoords.x > 1.0 || UVCoords.y < 0.0 || UVCoords.y > 1.0) return 1.0; 

注: 沒有通用的辦法說哪個更好。在涉及太陽光的地形環境中,您可能需要考慮超出範圍的地區已被廢棄。但是,例如,當您使用手電筒時,必須將用戶手中的手電筒視爲未點亮的