GLSL:为什么我计算的法线不能正常工作
GLSL : Why are my calculated normals not working properly
我正在尝试遵循 Ray Tracing in one Weekend tutorial 但我的法线看起来不像我期望的那样。
float hit_sphere(Sphere sphere, Ray r){
vec3 oc = r.origin - sphere.center;
float a = dot(r.direction,r.direction);
float b = 2.0 * dot(oc, r.direction);
float c = dot(oc, oc) - sphere.radius * sphere.radius;
float discriminant = b * b - 4 * a * c;
if(discriminant > 0){
return -1;
}
else{
return (-b -sqrt(discriminant))/(2.0 * a);
}
}
vec3 at(Ray ray, float p){
return ray.origin + p * ray.direction;
}
void main()
{
vec3 camera_origin = vec3(0,0,2);
vec2 st = gl_FragCoord.xy/vec2(x, y);
Ray r = Ray(camera_origin, normalize(vec3(st.x - 0.5, st.y - 0.5, 1.0)));
Sphere sphere = {vec3(0,0,0),0.5};
float p = hit_sphere(sphere, r);
if(p < 0.0){
vec3 N = normalize(at(r, p) - sphere.center);
FragColor = vec4(N.x + 1, N.y + 1, N.z + 1, 1);
}
else{
// FragColor = vec4(st.xy, 1.0, 1.0);
FragColor = vec4(1 - st.y+0.7, 1 - st.y+0.7,1 - st.y+0.9, 1.0);
}
}
请注意,每个正常颜色通道中的 + 1
是为了更明显地发现色差。
这就是我的法线的样子。
尽管这不是我所期望的这些法线的样子。
它们应该是这样的(不完全像这样但是很接近)
是什么错误或疏忽的问题导致的。
注意:来回移动不会改变情况
表达式
FragColor = vec4(N.x + 1, N.y + 1, N.z + 1, 1);
创建 [0, 2] 范围内的颜色。但是,颜色通道必须在 [0, 1]:
范围内
FragColor = vec4(N.xyz * 0.5 + 0.5, 1);
注意你也可以用abs
表示法线:
FragColor = vec4(abs(N.xyz), 1);
甚至用倒数最大颜色通道缩放:
vec3 nv_color = abs(N.xyz);
nv_color /= max(nv_color.x, max(nv_color.y, nv_color.z));
FragColor = vec4(nv_color, 1.0);
当discriminant > 0
p 为-1 时绘制法向量。其实你总是计算normalize(at(r, -1) - sphere.center)
。这是错误的,因为 p 需要是从原点到射线撞击球体的球体上的 pint 的距离。
当光线射到球体上时,p
>= 0。此时你要绘制法向量:
if (p < 0.0)
if (p >= 0.0) {
vec3 N = normalize(at(r, p) - sphere.center);
FragColor = vec4(N.xyz * 0.5 + 0.5, 1);
}
discriminant > 0
if (discriminant < 0){
return -1;
}
else {
return (-b -sqrt(discriminant))/(2.0 * a);
}
我正在尝试遵循 Ray Tracing in one Weekend tutorial 但我的法线看起来不像我期望的那样。
float hit_sphere(Sphere sphere, Ray r){
vec3 oc = r.origin - sphere.center;
float a = dot(r.direction,r.direction);
float b = 2.0 * dot(oc, r.direction);
float c = dot(oc, oc) - sphere.radius * sphere.radius;
float discriminant = b * b - 4 * a * c;
if(discriminant > 0){
return -1;
}
else{
return (-b -sqrt(discriminant))/(2.0 * a);
}
}
vec3 at(Ray ray, float p){
return ray.origin + p * ray.direction;
}
void main()
{
vec3 camera_origin = vec3(0,0,2);
vec2 st = gl_FragCoord.xy/vec2(x, y);
Ray r = Ray(camera_origin, normalize(vec3(st.x - 0.5, st.y - 0.5, 1.0)));
Sphere sphere = {vec3(0,0,0),0.5};
float p = hit_sphere(sphere, r);
if(p < 0.0){
vec3 N = normalize(at(r, p) - sphere.center);
FragColor = vec4(N.x + 1, N.y + 1, N.z + 1, 1);
}
else{
// FragColor = vec4(st.xy, 1.0, 1.0);
FragColor = vec4(1 - st.y+0.7, 1 - st.y+0.7,1 - st.y+0.9, 1.0);
}
}
请注意,每个正常颜色通道中的 + 1
是为了更明显地发现色差。
这就是我的法线的样子。
尽管这不是我所期望的这些法线的样子。 它们应该是这样的(不完全像这样但是很接近)
是什么错误或疏忽的问题导致的。
注意:来回移动不会改变情况
表达式
FragColor = vec4(N.x + 1, N.y + 1, N.z + 1, 1);
创建 [0, 2] 范围内的颜色。但是,颜色通道必须在 [0, 1]:
范围内FragColor = vec4(N.xyz * 0.5 + 0.5, 1);
注意你也可以用abs
表示法线:
FragColor = vec4(abs(N.xyz), 1);
甚至用倒数最大颜色通道缩放:
vec3 nv_color = abs(N.xyz);
nv_color /= max(nv_color.x, max(nv_color.y, nv_color.z));
FragColor = vec4(nv_color, 1.0);
当discriminant > 0
p 为-1 时绘制法向量。其实你总是计算normalize(at(r, -1) - sphere.center)
。这是错误的,因为 p 需要是从原点到射线撞击球体的球体上的 pint 的距离。
当光线射到球体上时,p
>= 0。此时你要绘制法向量:
if (p < 0.0)
if (p >= 0.0) {
vec3 N = normalize(at(r, p) - sphere.center);
FragColor = vec4(N.xyz * 0.5 + 0.5, 1);
}
discriminant > 0
if (discriminant < 0){
return -1;
}
else {
return (-b -sqrt(discriminant))/(2.0 * a);
}