光线跟踪器中平面上反射球体上的奇怪补丁

2024-06-06 17:45:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用python编写一个小的光线跟踪器,一切都很好,但是当我实现平面几何体时,反射球体的底部会有奇怪的补丁。下图:

我想这是因为在使用错误法线计算照明时出现了一些错误?但我不知道到底是什么

编辑:当我将平面向下移动一个单位时,它消失了,这可能是因为球体上方的点光源吗?为了检查这一点,我删除了所有的灯,但仍然,我得到了这个补丁

enter image description here

用于查找palne ray交点的代码:

class Plane(Shape):
    def __init__(self, color, y=0, specular=-1, reflective=0):
        self.specular = specular
        self.reflective = reflective
        self.center = Vec3(0,y,0)
        self.normal = Vec3(0,-1,0)
        self.color = color

    def intersect_at_point(self, origin, ray):

        denom = ray.dot(self.normal)

        if abs(denom) > 0.0001:
            diff  = self.center - ray
            t = diff.dot(self.normal) / denom

            if t > 0.0001:
                return t
        return None

跟踪光线功能

def trace_ray(self, origin, direction, t_min, t_max, depth):



    closest_object, closest_t = self.closest_intersection(origin, direction, t_min, t_max)

    if closest_object == None:
        return Vec3(173/255, 216/255, 230/255)

    # Compute local color
    P = origin + closest_t * direction  # Compute intersection
    N = P - closest_object.center  # Compute  normal at intersection
    N = N / N.mag()
    local_color = closest_object.color * self.compute_light(P, N)

    # If we hit the recursion limit or the object is not reflective, we're done
    r = closest_object.reflective
    if depth <= 0 or r <= 0:
        return local_color

    # Compute the reflected color
    R = self.reflect_ray(-1*direction, N)
    reflected_color = self.trace_ray(P, R, 0.001, math.inf, depth - 1)

    return local_color * (1 - r) + reflected_color * r

最近交点法

  def closest_intersection(self, O, D, t_min, t_max):
        closest_t = math.inf
        closest_object = None

        for object in self.world.objects:
            t1, t2 = object.intersect_at_point(O, D)

            if (t_min < t1 < t_max) and t1 < closest_t:
                closest_t = t1
                closest_object = object

            if (t_min < t2 < t_max) and t2 < closest_t:
                closest_t = t2
                closest_object = object

        for plane in self.world.planes:

            t = plane.intersect_at_point(O,D)

            if t and (t_min < t < t_max) and t < closest_t:
                    closest_t = t
                    closest_object = plane

        return closest_object, closest_t

计算光照法

def compute_light(self, Point, Normal):

    i = 0.0
    P = Point
    N = Normal

    for light in self.world.lights:
        if light.type == 'ambient':
            i += light.intensity
        else:
            if light.type == 'point':
                L = light.position - P
                t_max = 1

            if light.type == 'directional':
                L = light.direction
                t_max = math.inf

            # Shadow check
            shadow_sphere, shadow_t = self.closest_intersection(P, L, 0.001, t_max)
            if shadow_sphere != None:
                continue

            n_dot_l = N.dot(L)

            if n_dot_l > 0:
                # print(f'light intensity {light.intensity}')
                i+= light.intensity * n_dot_l / (N.mag() * L.mag())

    return i

Tags: selfreturnifobjectdefmindotmax