光线跟踪阴影显示错误的问题

发布于 09-01 23:03 字数 2250 浏览 19 评论 0

刚刚开始写光线跟踪,今天准备实现阴影的效果,但是发现了一些问题。
先上图:
图片描述

球体自身的阴影叠加在了球体上方,
并且来自其他球体的影子显示也不正确。我想了很久也没发现问题在哪。
还请各位前辈指点一下。

相关代码:

RGBColor Phong::Shade(ShadeRec &sr)
{
    Vector3D wo(-sr.m_ray.d);
    RGBColor L = m_ambientBRDF->rho(sr, wo) * sr.m_world.m_ambient->L(sr);
    int lightsNum = sr.m_world.m_lights.size();

    for (int i = 0; i < lightsNum; ++i)
    {
        Vector3D wi = sr.m_world.m_lights[i]->GetDirection(sr);
        float ndotwi = sr.m_hitPointNormal * wi;

        if(ndotwi > 0.0)
        {
            bool inShadow = false;

            if(sr.m_world.m_lights[i]->castsShadow())
            {
                Ray shadowRay((sr.m_worldHitPoint + kEpsilon), wi);
                inShadow = sr.m_world.m_lights[i]->inShadow(shadowRay, sr);
            }

            if(!inShadow)
            {
                L += (m_diffuseBRDF->fr(sr, wo, wi) + m_specularBRDF->fr(sr, wo, wi))
                    * sr.m_world.m_lights[i]->L(sr) * ndotwi;
            }
        }
    }

    return L;
}

bool PointLight::inShadow(const Ray &shadowray, const ShadeRec &sr)
{
    float ht(sr.m_t);
    float t;
    int ObjectNum = sr.m_world.m_objects.size();
    float d = m_location.distance(shadowray.o);

    for (int i = 0; i < ObjectNum; ++i)
    {
        if(sr.m_world.m_objects[i]->ShadowHit(shadowray, t) && t < d)
        {
            return true;
        }
    }

    return false;
}


bool Sphere::ShadowHit(const Ray &ray, float &tmin) const
{
    const double ep = 0.01;

    double t0, t1;
    Vector3D oc = ray.o - center;
    double a = ray.d * ray.d;
    double b = 2.0 * oc * ray.d;
    double c = oc * oc - radius * radius;
    double disc = b * b - 4.0 * a * c;

    if (disc < 0.0)
    {
        return false;
    }

    double e = sqrt(disc);
    double denom = 2.0 * a;
    
    t0 = (-b - e) / denom;

    if (t0 > ep)
    {
        tmin = t0;
        return true;
    }

    t1 = (-b + e) / denom;

    if (t1 > ep)
    {
        tmin = t1;
        return true;
    }

    return true;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

記柔刀2022-09-08 23:03:34

论变量名起名字的重要性,写成这样我都不知道你在写什么。不过根据我的经验,你可能是在计算一个点的阴影的时候,忘记判断可能造成阴影的物体是不是不在点和光源的中间,或者由于笔误而造成了等价效果。

还有,当你获得一个交点要计算阴影的时候,可能要把这个点往法向方向往外移动一个epsilon。我看你好像做了类似的事情。

解决这个问题的方法:给你的代码写上详细的注释,写着写着你就开窍了。

最后,我给一个我以前写的ray tracing给你参考。我写的也比较随便,只做了反射、折射、阴影、AO和一些贴图功能。完全没有性能优化,代码怎么好看怎么写。给复杂对象做求交的时候完全是平均切分的kd-tree(正常的做法是根据点的分布来切,尽量把空白的地方切掉)。

图形学真是一个打发时间的好东西系列

http://www.cppblog.com/vczh/archive/2011/01/09/138196.html
http://www.cppblog.com/vczh/archive/2011/01/21/138990.html
http://www.cppblog.com/vczh/archive/2011/01/22/139112.html

Vczhsim_013_B.jpg

Vczhsim_012.jpg

旧话新听2022-09-08 23:03:34

1 没有看到您的 kEpsilon 在何处计算的,我猜您想要表达的意思应该是浮在交点表面上一点点的位置重新投射shadow ray,那么是不是应该使用 kEpsilon * normal 来作为bias?

2 inShadow函数没有判断t < 0 的情况,是不是在ShadowHit里计算intersection的时候就已经排除了负向?

3 注意到你的wo有做反向来获取Li Direction 不知道在获取shadow ray方向的时候, wi=light::GetDirection(sr)的方向是否是正确的?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文