Ho implementato la mappatura shadow di base per la prima volta in OpenGL usando shader e sto affrontando alcuni problemi. Di seguito puoi vedere un esempio della mia scena renderizzata:
Il processo di mappatura dell'ombra che sto seguendo è che eseguo il rendering della scena sul framebuffer utilizzando una matrice di visualizzazione dal punto di vista della luce e le matrici di proiezione e modello utilizzate per il rendering normale.
Nel secondo passaggio, invio la matrice MVP sopra dal punto di vista della luce allo shader di vertice che trasforma la posizione in spazio luminoso. Lo shader di frammenti divide la prospettiva e cambia la posizione in coordinate di trama.
Ecco il mio shader vertice,
#version 150 core
uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;
uniform mat4 MVPMatrix;
uniform mat4 lightMVP;
uniform float scale;
in vec3 in_Position;
in vec3 in_Normal;
in vec2 in_TexCoord;
smooth out vec3 pass_Normal;
smooth out vec3 pass_Position;
smooth out vec2 TexCoord;
smooth out vec4 lightspace_Position;
void main(void){
pass_Normal = NormalMatrix * in_Normal;
pass_Position = (ModelViewMatrix * vec4(scale * in_Position, 1.0)).xyz;
lightspace_Position = lightMVP * vec4(scale * in_Position, 1.0);
TexCoord = in_TexCoord;
gl_Position = MVPMatrix * vec4(scale * in_Position, 1.0);
}
E il mio shader di frammenti,
#version 150 core
struct Light{
vec3 direction;
};
uniform Light light;
uniform sampler2D inSampler;
uniform sampler2D inShadowMap;
smooth in vec3 pass_Normal;
smooth in vec3 pass_Position;
smooth in vec2 TexCoord;
smooth in vec4 lightspace_Position;
out vec4 out_Color;
float CalcShadowFactor(vec4 lightspace_Position){
vec3 ProjectionCoords = lightspace_Position.xyz / lightspace_Position.w;
vec2 UVCoords;
UVCoords.x = 0.5 * ProjectionCoords.x + 0.5;
UVCoords.y = 0.5 * ProjectionCoords.y + 0.5;
float Depth = texture(inShadowMap, UVCoords).x;
if(Depth < (ProjectionCoords.z + 0.001)) return 0.5;
else return 1.0;
}
void main(void){
vec3 Normal = normalize(pass_Normal);
vec3 light_Direction = -normalize(light.direction);
vec3 camera_Direction = normalize(-pass_Position);
vec3 half_vector = normalize(camera_Direction + light_Direction);
float diffuse = max(0.2, dot(Normal, light_Direction));
vec3 temp_Color = diffuse * vec3(1.0);
float specular = max( 0.0, dot( Normal, half_vector) );
float shadowFactor = CalcShadowFactor(lightspace_Position);
if(diffuse != 0 && shadowFactor > 0.5){
float fspecular = pow(specular, 128.0);
temp_Color += fspecular;
}
out_Color = vec4(shadowFactor * texture(inSampler, TexCoord).xyz * temp_Color, 1.0);
}
Uno dei problemi è l'ombreggiamento di se stessi, come puoi vedere nella foto, la cassa ha la sua ombra proiettata su se stessa. Quello che ho provato è abilitare l'offset poligonale (ovvero glEnable (POLYGON_OFFSET_FILL), glPolygonOffset (GLfloat, GLfloat)) ma non è cambiato molto. Come vedi nello shader di frammenti, ho messo un valore di offset statico di 0,001 ma devo cambiare il valore in base alla distanza della luce per ottenere effetti più desiderabili, il che non è molto utile. Ho anche provato a usare l'abbattimento frontale quando eseguo il rendering sul framebuffer, ma non è cambiato molto.
L'altro problema è che i pixel esterni al frustum della vista della Luce vengono ombreggiati. L'unico oggetto che dovrebbe essere in grado di proiettare ombre è la cassa. Immagino che dovrei scegliere una proiezione più appropriata e visualizzare le matrici, ma non sono sicuro di come farlo. Quali sono alcune pratiche comuni, dovrei scegliere una proiezione ortografica?
Da googling un po ', capisco che questi problemi non sono così banali. Qualcuno ha qualche soluzione facile da implementare per questi problemi. Potresti darmi qualche consiglio aggiuntivo?
Per favore, chiedimi se hai bisogno di maggiori informazioni sul mio codice.
Ecco un confronto con e senza mappatura dell'ombra di un primo piano della cassa. L'auto-ombra è più visibile.