因此,在我正在构建的光线追踪器中,我得到了折射作用以用于具有球形效果的球体,但是玻璃球体看起来并不是特别好。我相信折射的数学是正确的,因为光线似乎在弯曲,从而使您所期望的方式发生了反转,但是它看起来不像玻璃,而是像纸或其他东西。

我已经读到全内反射是造成玻璃看起来像的大部分原因,但是当我测试看我的折射光线是否超过临界角时,它们都没有,所以我的玻璃球没有全内反射。我不确定这是否正常还是做错了什么。我已经在下面发布了我的折射代码,因此,如果有人有任何建议,我想听听他们的建议。

/*
 * Parameter 'dir' lets you know whether the ray is starting
 * from outside the sphere going in (0) or from in the sphere
 * going back out (1).
 */
void Ray::Refract(Intersection *hit, int dir)
{

    float n1, n2;
    if(dir == 0){ n1 = 1.0; n2 = hit->mat->GetRefract(); }
    if(dir == 1){ n1 = hit->mat->GetRefract(); n2 = 1.0; }

    STVector3 N = hit->normal/hit->normal.Length();
    if(dir == 1) N = -N;
    STVector3 V = D/D.Length();
    double c1 = -STVector3::Dot(N, V);
    double n = n1/n2;

    double c2 = sqrt(1.0f - (n*n)*(1.0f - (c1*c1)));

    STVector3 Rr = (n * V) + (n * c1 - c2) * N;

    /*These are the parameters of the current ray being updated*/
    E = hit->point;  //Starting point
    D = Rr;          //Direction
}


在我的主要光线跟踪方法RayTrace()中调用该方法,该方法以递归方式运行。以下是折射的一小部分:

    if (hit->mat->IsRefractive())
    {
        temp.Refract(hit, dir); //Temp is my ray that is being refracted
        dir++;
        result += RayTrace(temp, dir); //Result is the return RGB value.
    }

最佳答案

没错,您永远不会在一个球体内获得全内反射(从外部看到)。那是由于对称性:球体内的射线将在两端以相同的角度撞击表面,这意味着,如果它在一端超过临界角,那么在另一端也必须超过临界角(所以首先将无法从外部进入球体)。

但是,根据Fresnel's law,您仍然会得到很多局部反射。看起来不是您的代码说明了这一点,这可能就是您的杯子看起来很假的原因。尝试包括它,看看是否有帮助。

(是的,这意味着您的光线在碰到折射表面时会一分为二。这是现实情况,因此您只需忍受它即可。您可以追踪两条路径,或者如果使用的是无论如何,请使用适当的权重随机采样其中之一。)

附言如果您不想处理偏振光之类的问题,则可能只想在菲涅耳方程式中使用Schlick's approximation即可。

10-07 18:50