【问题标题】:Finding the length of a ray within a cube求立方体内光线的长度
【发布时间】:2010-11-22 17:10:17
【问题描述】:

我有一条光线,从相机向外射出,我需要找到光线在立方体内的长度。请注意,相机可能在立方体内部,在这种情况下,它应该返回到立方体边缘的距离。

它用于着色器,因此它应该相对较小并且涉及最少的分支。

有什么想法吗?

【问题讨论】:

    标签: algorithm math shader


    【解决方案1】:

    要将射线与凸多面体相交,请将射线与包含每个面的平面相交。

    假设射线从 q 开始,方向为 r。那么对于标量参数t,射线上的任何点都可以表示为q + t r。现在假设我们要使这条射线与方程 p · n = k 给出的平面相交(其中 n 是一个垂直于面部的向外指向单元)。当光线与平面相交时

    (q + t r) · n = k

    也就是说,当

    q · n + t r · n = k

    等等

    t = (k - q · n) / r · n

    光线在r·n为负时进入面部,当r·n为正时退出.当 r · n 为零时,光线平行于面部。您需要检查这种情况以避免被零除;在这种情况下,如果 q · n > k,则射线完全错过了多面体。

    所以为你的多面体的所有面找到 t 并让 tin 成为最大值 t光线进入面的点,tout 是光线离开面的点的最小值 t。那么多面体中射线的长度为

    max(max(tout, 0) - max(tin, 0), 0 ) / |r|

    如果 r 是单位向量,则可以避免此处的除法。两个内部的 max(t, 0) 是处理相机在立方体内部或立方体在相机后面的情况所必需的。外部 max(..., 0) 用于处理光线完全错过立方体的情况(在这种情况下 tin 将大于 tout)。

    恐怕我不知道如何用你的着色器语言来表示这个计算,更不用说如何无分支地这样做了。

    【讨论】:

    • 谢谢!翻译成openGL的着色器语言是没有问题的。由于我的立方体是轴对齐的,我可以进一步简化你已经很紧凑的方程!这会很好用。
    • 这里的k是什么?看起来它应该是平面偏移,p0,但如果是这样,为什么不说明呢?
    • @opa:你说得对|k|是平面到原点的垂直距离,但我假设 OP 熟悉平面方程,所以不需要我提醒他们这个细节。
    • 平面方程根据维基百科定义为(p-p0)*n = 0。这也是我之前见过的唯一的飞机定义。对于熟悉该定义的人来说,这个定义看起来很陌生。
    • @opa:你只需要扩展括号:if (p − p₀)·n = 0 then p·n = p₀·n = k
    【解决方案2】:

    如果你告诉我们你到底需要什么就可以了。您可以通过渲染立方体然后读取包含从相机到立方体每个可见点的距离的 z 缓冲区来轻松完成此操作。中间的点是相机正在看的地方。

    否则,您将需要对立方体的每个平面执行ray-plane intersection,检查交点是否在立方体的范围内,并检查它是否不在相机后面。您可以获得以下三种情况之一:

    1. 没有交叉路口
    2. 一个交叉点 - 你在立方体内,计算交叉点和相机位置之间的距离
    3. 两个交点 - 你在立方体外,计算两个交点之间的距离
    4. 无限多个交点 - 视图向量是立方体的切线,只需丢弃切平面交点,只取两个相邻平面的两个交点

    您需要将立方体信息发送到着色器单元。所有着色器的计算都是相同的,所以我看不出将它放入着色器中的意义——最好在 CPU 上计算一次。此外,它涉及分支(我不知道如何避免它)。

    【讨论】:

    • 对不起,我会记得解释更多关于我将来在做什么。我正在模拟一个立方体形状的大气,我需要知道我们正在查看多少大气来确定颜色。我会考虑使用 z-buffer,因为我也可以为风景渲染逼真的雾。计算也是按顶点完成的。
    • 为什么要使用立方体?球体(或半球体)绝对更适合大气。此外,交点计算也容易得多。
    • 因为我们的世界是一个巨大的立方体,一个立方体的世界应该不亚于立方体的气氛。
    猜你喜欢
    • 2019-11-29
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    相关资源
    最近更新 更多