Python 光线追踪

6 投票
1 回答
3551 浏览
提问于 2025-04-16 14:16

我正在用纯Python构建一个简单的光线追踪器(纯粹是为了好玩),但是遇到了一些问题。

我现在的场景设置是这样的:

  1. 相机位于 0, -10, 0,朝着 y 轴方向看。
  2. 有一个半径为 1 的球体,位置在 0, 0, 0
  3. 成像平面距离相机 1 的地方,宽和高都是 0.5

我通过成像平面均匀随机地发射光子,如果光子碰到了物体,我就在图像画布上对应的点画一个红点,表示光线经过的地方。

我的碰撞检测代码(目前只处理球体):

def intersection(self, ray):
  cp = self.pos - ray.origin
  v = cp.dot(ray.direction)
  discriminant = self.radius**2  - cp.dot(cp) + v * v

  if discriminant < 0:
    return False
  else:
    return ray.position(v - sqrt(discriminant)) # Position of ray at time t

还有我的渲染代码(它渲染一定数量的光子,而不是逐像素渲染):

def bake(self, rays):
  self.image = Image.new('RGB', [int(self.camera.focalplane.width * 800), int(self.camera.focalplane.height * 800)])
  canvas = ImageDraw.Draw(self.image)

  for i in xrange(rays):
    x = random.uniform(-camera.focalplane.width / 2.0, camera.focalplane.width / 2.0)
    z = random.uniform(-camera.focalplane.height / 2.0, camera.focalplane.height / 2.0)

    ray = Ray(camera.pos, Vector(x, 1, z))

    for name in scene.objects.keys():
      result = scene.objects[name].intersection(ray)

      if result:
        n = Vector(0, 1, 0)
        d = ((ray.origin - Point(self.camera.pos.x, self.camera.pos.y + self.camera.focalplane.offset, self.camera.pos.z)).dot(n)) / (ray.direction.dot(n))
        pos = ray.position(d)

        x = pos.x
        y = pos.y

        canvas.point([int(self.camera.focalplane.width * 800) * (self.camera.focalplane.width / 2 + x) / self.camera.focalplane.width,
                      int(self.camera.focalplane.height * 800) * (self.camera.focalplane.height / 2 + z) / self.camera.focalplane.height],
                      fill = 128)

理论上应该能正常工作,但当我渲染测试图像时,看到的却没有任何像球体轮廓的东西:

enter image description here

我本来期待看到这样的效果:

enter image description here

有没有人知道我的代码为什么不正常工作?我在这部分代码上调整和重写了太久了……

1 个回答

8

你有没有把光线的方向向量进行标准化?

撰写回答