J'ai implémenté le mappage d'ombres de base pour la première fois dans OpenGL à l'aide de shaders et je rencontre des problèmes. Ci-dessous, vous pouvez voir un exemple de ma scène rendue:
Le processus de mappage des ombres que je suis consiste à rendre la scène au tampon d'images en utilisant une matrice de vue du point de vue de la lumière et les matrices de projection et de modèle utilisées pour le rendu normal.
Dans la deuxième passe, j'envoie la matrice MVP ci-dessus du point de vue de la lumière au vertex shader qui transforme la position en espace lumineux. Le fragment shader divise la perspective et change la position en coordonnées de texture.
Voici mon vertex shader,
#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);
}
Et mon fragment shader,
#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);
}
L'un des problèmes est l'ombrage automatique comme vous pouvez le voir sur la photo, la caisse a sa propre ombre projetée sur elle-même. Ce que j'ai essayé, c'est d'activer le décalage de polygone (c'est-à-dire glEnable (POLYGON_OFFSET_FILL), glPolygonOffset (GLfloat, GLfloat)) mais cela n'a pas beaucoup changé. Comme vous le voyez dans le fragment shader, j'ai mis une valeur de décalage statique de 0,001 mais je dois changer la valeur en fonction de la distance de la lumière pour obtenir des effets plus souhaitables, ce qui n'est pas très pratique. J'ai également essayé d'utiliser l'abattage de face avant lors du rendu sur le framebuffer, cela n'a pas trop changé.
L'autre problème est que les pixels en dehors du tronc de vue de la lumière sont ombrés. Le seul objet censé pouvoir projeter des ombres est la caisse. Je suppose que je devrais choisir des matrices de projection et de vue plus appropriées, mais je ne sais pas comment faire cela. Quelles sont les pratiques courantes, dois-je choisir une projection orthographique?
De googler un peu, je comprends que ces questions ne sont pas si triviales. Quelqu'un at-il des solutions faciles à implémenter à ces problèmes? Pourriez-vous me donner quelques conseils supplémentaires?
Veuillez me demander si vous avez besoin de plus d'informations sur mon code.
Voici une comparaison avec et sans cartographie d'ombre d'un gros plan de la caisse. L'auto-observation est plus visible.