我正在努力使用有符号距离函数 (SDF) 在 OpenGL 着色器中实现光线行进阴影。光源放置在原点 (0,0,0),我使用光线行进来计算场景中对象的阴影。但是,我遇到了一个问题,当物体靠近或穿过光源时,阴影会出现倒转。影子投到了对面,我不知道自己做错了什么
这是我的片段着色器的简化版本,它执行光线行进来计算阴影:
#version 330 core
out vec4 FragColor; // outputs a vector4 frag color
in vec3 color;
in vec3 Normal;
in vec3 CurrentPos;
uniform vec4 lightColor;
uniform vec3 lightPos;
// Ray marching
uniform vec3 sphereOrigin[4];
uniform int sphereRadius[4];
float SDF(in vec3 p, in vec3 c, float r) { // compute the distance from the camera to a sphere
return length(c - p) - r;
}
float computeShadow() {
float t = 0.0;
vec3 rayDir = normalize(lightPos - CurrentPos); // Direction from surface to light
for (int i = 0; i < 10 && t < 100.0; i++) {
vec3 currentPos = lightPos + rayDir * t;
float minH = 1e6; // Large initial value to track closest hit
for (int k = 0; k < 4; k++) {
float h = SDF(currentPos, sphereOrigin[k], sphereRadius[k]);
minH = min(minH, h);
}
if (minH < 0.001) return 0.0; // In shadow
t += minH; // Move along the ray
}
return 1.0; // No shadow
}
void main() {
vec4 objectColor = vec4(color, 1.0);
float ambient = 0.2;
vec4 result = vec4(0.0, 0.0, 0.0, 1.0);
vec3 lightDir = normalize(lightPos - CurrentPos);
float diff = max(dot(normalize(Normal), lightDir), 0.0f);
float shadow = computeShadow();
result = objectColor * lightColor * (diff * shadow + ambient);
FragColor = result;
}
在顶点着色器中,这是 CurrentPos 接收的内容:
CurrentPos = vec3(model * vec4(aPos.x * scale, aPos.y * scale, aPos.z * scale, 1.0f));
正如前面提到的,阴影是反转的,所以我只需要对灯光的位置做同样的事情
vec3 currentPos = rayDir - rayDir * t;