光线追踪折射看起来“假”的问题

3
在我正在构建的光线追踪器中,我已经让球体折射和焦散效果生效了,然而玻璃球看起来并不是特别好。我相信折射数学是正确的,因为光线似乎弯曲并且倒转了你期望的方式,但它看起来不像玻璃,只是像纸或其他东西。
我读到总反射在很大程度上造就了玻璃的外观,然而当我测试任何一个折射光线是否超过了临界角时,它们都没有,所以我的玻璃球没有总反射。我不确定这是否正常或者我做错了什么。我在下面发布了我的折射代码,如果有人有任何建议,我会非常乐意听取。
/*
 * 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.
    } 
1个回答

5
你说得对,从外部看,球体内部永远不会出现完全内反射。这是由于对称性:球体内的光线在两端以相同的角度击中表面,这意味着如果它在一个端点超过了临界角,那么在另一个端点也必须超过临界角(因此根本无法从外部进入球体)。
然而,根据Fresnel's law,仍将获得大量的部分反射。看起来你的代码没有考虑到这一点,这可能是为什么你的玻璃看起来假的原因。试着包括它,并看看是否有帮助。
(是的,这意味着你的光线每次击中折射表面时会分裂成两个。这在现实中发生,所以你只能接受它。你可以跟踪两条路径,或者如果你正在使用随机射线跟踪算法,则用适当的权重随机采样其中之一。)

提示:如果你不想处理像光偏振这样的东西,可以使用Schlick's approximation来近似菲涅耳方程。


谢谢!我尝试了实现Schlick的近似算法,虽然仍然有一些错误,但是我的球看起来更像玻璃了!=) - user1855952

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接