Ich habe zum ersten Mal eine grundlegende Schattenzuordnung in OpenGL mithilfe von Shadern implementiert und habe einige Probleme. Unten sehen Sie ein Beispiel meiner gerenderten Szene:
Der Prozess der Schattenzuordnung, dem ich folge, besteht darin, dass ich die Szene unter Verwendung einer Ansichtsmatrix aus der Sicht des Lichts und der für das normale Rendern verwendeten Projektions- und Modellmatrizen in den Framebuffer rendere.
Im zweiten Durchgang sende ich die obige MVP-Matrix aus der Sicht des Lichts an den Vertex-Shader, der die Position in den Lichtraum umwandelt. Der Fragment-Shader teilt die Perspektive und ändert die Position in Texturkoordinaten.
Hier ist mein 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);
}
Und mein 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);
}
Eines der Probleme ist die Selbstbeschattung, wie Sie auf dem Bild sehen können. Die Kiste hat ihren eigenen Schatten auf sich geworfen. Ich habe versucht, den Polygonversatz zu aktivieren (dh glEnable (POLYGON_OFFSET_FILL), glPolygonOffset (GLfloat, GLfloat)), aber es hat sich nicht viel geändert. Wie Sie im Fragment-Shader sehen, habe ich einen statischen Versatzwert von 0,001 festgelegt, aber ich muss den Wert abhängig von der Entfernung des Lichts ändern, um wünschenswertere Effekte zu erzielen, was nicht sehr praktisch ist. Ich habe auch versucht, beim Rendern des Framebuffers das Front-Face-Culling zu verwenden, was sich auch nicht wesentlich geändert hat.
Das andere Problem ist, dass Pixel außerhalb des Sichtstumpfes des Lichts schattiert werden. Das einzige Objekt, das Schatten werfen soll, ist die Kiste. Ich denke, ich sollte eine geeignetere Projektion auswählen und Matrizen anzeigen, aber ich bin mir nicht sicher, wie ich das machen soll. Was sind einige gängige Praktiken, sollte ich eine orthografische Projektion auswählen?
Wenn ich ein bisschen google, verstehe ich, dass diese Probleme nicht so trivial sind. Hat jemand einfach zu implementierende Lösungen für diese Probleme. Könnten Sie mir zusätzliche Tipps geben?
Bitte fragen Sie mich, ob Sie weitere Informationen zu meinem Code benötigen.
Hier ist ein Vergleich mit und ohne Schattenkartierung einer Nahaufnahme der Kiste. Die Selbstbeschattung ist sichtbarer.