ฉันใช้การทำแผนที่เงาพื้นฐานเป็นครั้งแรกใน OpenGL โดยใช้ shaders และฉันประสบปัญหาบางอย่าง ด้านล่างคุณสามารถดูตัวอย่างของฉากที่แสดงผลของฉัน:
กระบวนการของการแมปเงาที่ฉันกำลังติดตามคือฉันแสดงฉากให้กับ framebuffer โดยใช้ View Matrix จากมุมมองแสงและเมทริกซ์การฉายและแบบจำลองที่ใช้สำหรับการเรนเดอร์ปกติ
ในรอบที่สองฉันส่งเมทริกซ์ MVP ด้านบนจากมุมมองแสงไปยังตัวแบ่งจุดยอดซึ่งเปลี่ยนตำแหน่งเป็นพื้นที่แสง ส่วนของ 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);
}
และส่วนที่แตกของฉัน
#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);
}
หนึ่งในปัญหาคือเงาตัวเองอย่างที่คุณเห็นในภาพลังมีเงาของตัวเอง สิ่งที่ฉันได้ลองคือการเปิดใช้งานรูปหลายเหลี่ยมชดเชย (เช่น glEnable (POLYGON_OFFSET_FILL), glPolygonOffset (GLfloat, GLfloat) แต่มันไม่ได้เปลี่ยนแปลงอะไรมาก อย่างที่คุณเห็นในตัวแบ่งส่วนฉันใส่ค่าออฟเซ็ตคงที่ 0.001 แต่ฉันต้องเปลี่ยนค่าขึ้นอยู่กับระยะทางของแสงเพื่อให้ได้เอฟเฟ็กต์ที่ต้องการมากขึ้นซึ่งไม่ค่อยมีประโยชน์ ฉันยังลองใช้การเผชิญหน้าด้านหน้าเมื่อฉันแสดงผลกับ framebuffer นั่นก็ไม่ได้เปลี่ยนไปเหมือนกัน
ปัญหาอื่นคือพิกเซลที่อยู่นอกมุมมองของแสงจะได้รับการแรเงา วัตถุเดียวที่ควรจะสามารถหล่อเงาได้คือลัง ฉันเดาว่าฉันควรเลือกการฉายภาพที่เหมาะสมกว่าและดูเมทริกซ์ แต่ฉันไม่แน่ใจว่าจะทำอย่างไร ฉันควรเลือกวิธีการฉายภาพแบบออโทกราฟ
ฉันเข้าใจว่าปัญหาเหล่านี้ไม่ใช่เรื่องเล็กน้อย ไม่มีใครมีวิธีแก้ไขปัญหาเหล่านี้ได้ง่ายบ้างไหม คุณให้คำแนะนำเพิ่มเติมกับฉันได้ไหม
โปรดถามฉันหากคุณต้องการข้อมูลเพิ่มเติมเกี่ยวกับรหัสของฉัน
นี่คือการเปรียบเทียบที่มีและไม่มีการแมปเงาของระยะใกล้ของลังไม้ เงาตัวเองสามารถมองเห็นได้มากขึ้น