gpt4 book ai didi

graphics - 当光线从嵌套对象内部开始时如何处理折射

转载 作者:行者123 更新时间:2023-12-04 17:28:14 28 4
gpt4 key购买 nike

我正在构建一个用于教育目的的简单光线跟踪器,并希望为对象添加折射。使用斯内尔定律,我能够在交点处递归地创建一条新射线。光线追踪器目前仅支持球体,我使用了一个场景,其中多个球体相互嵌套并具有不同的折射率。

如果我从球体外部开始一条射线,一切似乎都很简单。您从场景的折射率开始,一旦碰到第一个球体,就使用之前的折射率和球体 Material 的折射率来折射光线,直到碰到下一个球体,依此类推。使用交叉点的法线,我可以确定我是进入还是离开球体。

但是,我不明白我应该如何处理球体叶子以及如果光线不在场景的外部开始该怎么办。

  • 我可以只拿一堆折射率并在离开球体后立即向上一层吗?
  • 如果我从球体内部开始,我如何确定我必须以什么折射率开始?

  • 示例

    您有三个球体,从外到内的折射率分别为 0.9、1.1 和 0.8。空气指数为1.0
  • 您的相机位于球体之外并指向球体的中心:
  • 起始索引为 1.0,您首先击中索引为 0.9 的外球体并从 1.0 折射到 0.9,并保存您的光线现在位于 0.9 Material
  • 您击中中间球体并注意到 Material 常数为 1.1,因为您保存了 0.9,您知道除了 0.9
  • 之外,您还必须从 0.9 折射到 1.1 并保存 1.1。
  • 你击中了内部球体并从 1.1 折射到 0.8,并且到目前为止你已经保存了 0.9、1.1 和 0.8
  • 你再次击中内部球体(这次你退出它,所以你检查你保存的值并知道你必须切换回 1.1)
  • ...直到你在外面
  • 现在的问题,当相机在球体内时。你不会知道你必须切换到什么折射率。
  • 最佳答案

    我有一个类似的光线追踪器(用 Python 编写)并偶然发现了同样的问题:为了正确计算物理,必须知道相交边界每一侧的折射率。这花了很长时间才优雅地解决,但最后我采用了这个解决方案/设计:

    设计

    1)场景——我有一个主场景对象(基本上是场景中所有对象的数组),你可能会有类似的东西。它存储几何对象。

    方法:

  • intersection_points(ray) - 返回所有交点的列表,按与射线的距离排序。
  • intersection_objects(ray) - 返回所有相交对象的列表,按与射线的距离排序。
  • containing_object(ray) - 返回包含射线的对象。
  • objects() - 以任意顺序返回所有对象的列表。

  • 注:场景向列表中添加了一个额外的对象:Scene_Boundary。这是一个巨大的盒子(或球体),它封装了整个场景,即一切都在这个边界内。

    2) 对象——使几何对象(例如您的球体)实现这些方法。

    方法:
  • contains(ray) - 返回真射线原点在物体内部,假如果在表面上,假如果在外面
  • ray_is_on_surface(ray) - 如果光线仅在表面上,则返回 True,否则返回 False。
  • intersection_points(ray) - 返回光线与物体的交点
  • surface_normal(ray) - 返回光线撞击表面的表面法向量(这将有助于菲涅尔反射和折射)

  • 对于光学计算,物体还必须具有折射率。

    实例变量:
  • refractive_index

  • 边界问题

    我们要解决的问题:边界内(n1)和外(n2)的折射率是多少?为此,我们遵循以下程序:

    1)在整个场景中跟踪光线:
    sphere # origin = (0,0,0), radius = 1
    ray # origin = (0,0,0), direction = (0,0,1) Note: the ray is inside the sphere
    scene.add_object(sphere)
    ipoints = scene.intersection_points(ray) # [ (0,0,1), (0,0,10) ]
    iobjects = scene.intersection_objects(ray) # [ Sphere, Scene_Boundary]

    请记住,这些是按与射线原点的距离排序的。 ipoints 和 iobjects 中的最后一项是光线与场景边界的交集。我们稍后会用到它!

    2) 只需通过查找包含对象即可找到 n1,例如:
    obj1 = scene.containing_object(ray) # Scene_Boundary
    n1 = obj1.refractive_index() # n1 = 1. Scene_Boundary always has refractive index of Air

    3) n2 是通过在 iobject 列表中向前查找一个对象来找到的,例如在伪代码中:
    index = iobjects.index_of_object(obj1)
    obj2 = iobjects[index+1]
    n2 = obj2.refractive_index() # n2 = 1.5 e.g. Glass

    4)获取曲面法线以备后用:
    normal = obj1.surface_normal(ray)

    您拥有计算正确反射和折射所需的所有信息。即使光线在对象之外,这也足够通用,但有时我确实需要实现一些逻辑过滤以使算法更健壮,但基本上就是这样!

    反射和折射

    您可以仅通过了解表面法线来反射矢量。在 Python 中使用 numpy 我这样做,
    def reflect_vector(normal, vector):
    d = numpy.dot(normal, vector)
    return vector - 2 * d * normal

    折射(如上所述)需要 n1 和 n2 值:
    def fresnel_refraction(normal, vector, n1, n2):
    n = n1/n2
    dot = np.dot(norm(vector), norm(normal))
    c = np.sqrt(1 - n**2 * (1 - dot**2))
    sign = 1
    if dot < 0.0:
    sign = -1
    refraction = n * vector + sign*(c - sign*n*dot) * normal
    return norm(refraction)

    最后,您将需要计算光线的反射系数,其中角度是光线方向与表面法线之间的角度(假设您的光线是“未极化的”)。将此与 0 和 1 之间的随机数进行比较,以确定是否发生反射。
    def fresnel_reflection(angle, n1, n2):
    assert 0.0 <= angle <= 0.5*np.pi, "The incident angle must be between 0 and 90 degrees to calculate Fresnel reflection."
    # Catch TIR case
    if n2 < n1:
    if angle > np.arcsin(n2/n1):
    return 1.0

    Rs1 = n1 * np.cos(angle) - n2 * np.sqrt(1 - (n1/n2 * np.sin(angle))**2)
    Rs2 = n1 * np.cos(angle) + n2 * np.sqrt(1 - (n1/n2 * np.sin(angle))**2)
    Rs = (Rs1/Rs2)**2
    Rp1 = n1 * np.sqrt(1 - (n1/n2 * np.sin(angle))**2) - n2 * np.cos(angle)
    Rp2 = n1 * np.sqrt(1 - (n1/n2 * np.sin(angle))**2) + n2 * np.cos(angle)
    Rp = (Rp1/Rp2)**2
    return 0.5 * (Rs + Rp)

    最后评论

    这一切都来自我尚未发布的 Python 光线追踪项目(!),但您可以在此处查看详细信息: http://daniel.farrell.name/freebies/pvtrace .我喜欢 python !这里列出了许多 Python 光线追踪项目, http://groups.google.com/group/python-ray-tracing-community/web/list-of-python-statistical-ray-tracers .最后,请注意您的示例中的分数折射率,该等式将分解。

    更新

    在我的光线追踪器中实现的屏幕截图,可在 http://github.com/danieljfarrell/pvtrace 获得
    alt text

    关于graphics - 当光线从嵌套对象内部开始时如何处理折射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3858662/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com