首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从渲染方程中添加cos(θ)会破坏渲染过程

从渲染方程中添加cos(θ)会破坏渲染过程
EN

Computer Graphics用户
提问于 2022-05-19 00:13:32
回答 2查看 173关注 0票数 2

我跟随射线追踪你的余生来实现射线追踪器,但是对数学的解释(主要是pdf部分)让我感到困惑,所以我按照渲染方程来理解背后的数学。结果,我用普通蒙特卡罗方法(由方程导出)对场景进行了采样,去除了渲染方程中的cos(θ),得到了一些正确的结果,但用cos(θ)得到了一幅不正确的暗图像。更糟糕的是,渲染没有收敛:随着样本数量的增加,渲染变得越来越暗。

从左到右:500个没有cos(θ)的样本,500个带有cos(θ)的样本,100个带有cos(θ)的样本:

代码并不复杂。对于每一次采样,相机向函数ray_trace(Ray ray, int depth)发送一条光线,当光线击中光线或在反射足够的时间(depth <= 0)后找不到光线时,该函数终止。当它碰到场景中的某物时(除了光之外,场景中唯一的物质是兰伯材料),散射射线是由物质的scatter(Ray ray, Intersection intersection, Ray &scattered_ray)函数产生的。在Lambertian的scatter()函数中,散射射线是由半球周围的均匀采样产生的。然后这条散射射线成为函数ray_trace中的新射线,从而depth = depth-1,并开始另一轮射线追踪。

代码语言:javascript
复制
{
    // initially, this ray is generated from a camera
    if (depth <= 0)
    {
        // return black when no light found
        return Vec3(0.0, 0.0, 0.0);
    }

    auto intersection = scene.intersect(ray);

    if (!intersection.intersected)
    {
        // return black when hits nothing
        return Vec3(0.0, 0.0, 0.0);
    }

    if (intersection.hit_a_light)
    {
        // found a light
        return intersection.material.emit(...);
    }

    Ray scattered_ray;
    Vec3 attenuation = intersection.material.scatter(ray, intersection, &scattered_ray);

    if (with_cosine_theta)
    {
        Vec3 cosine_theta = dot(intersection.normal.normalize(), scattered_ray.direction.normalize());
        return cosine_theta * attenuation * ray_trace(scattered_ray, depth - 1);
    }
    else
    {
        // without cosine(theta)
        return attenuation * ray_trace(scattered_ray, depth - 1);
    }
}

Vec3 Lambertian::scatter(Ray ray, Intersection intersection, Ray &scattered_ray)
{
    double phi = random(0.0, 2.0 * PI);
    double sin_phi = sine(phi);
    double cos_phi = cosine(phi);

    double cos_theta = random(-1.0, 1.0);
    double sin_theta = sqrt(1 - cos_theta * cos_theta);

    Vec3 scattered_direction = Vec3(sin_phi * sin_theta, cos_phi * sin_theta, cos_theta);

    // generate random direction in a hemisphere
    if (dot(scattered_direction, intersection.normal) < 0)
    {
        scattered_direction = -scattered_direction;
    }

    scattered_ray.origin = intersection.hit_point;
    scattered_ray.direction = scattered_direction;

    return this.albedo;
}

有人能指出是什么让我的渲染错误吗?

最新情况:

遵循着电灯泡的想法,我尝试了这两种方法(https://codeshare.io/bvR8ev上的代码):

  • cos(θ)保持在ray_trace(),均匀样本半球在scatter() (WITH_COSINE=trueUNIFORM_SAMPLE=true)
  • 去除cos(θ)ray_trace()和样本半球中的cos(θ)重要性(WITH_COSINE=falseUNIFORM_SAMPLE=false)

对于第一种方法,我有(100/200/500样本):

关于第二种方法(100/200/500样本):

从左到右:100个样本,200个样本,500个样本

EN

回答 2

Computer Graphics用户

发布于 2022-05-19 08:09:43

没有余弦的渲染可能是错误的,因为您使用的是均匀球面采样,并且余弦必须在那里(除非假设brdfs包含1/cos(θ)项)。也要这样做:

代码语言:javascript
复制
pdf = 1.0/(2.0*PI);
return cosine_theta * attenuation / pdf * ray_trace(scattered_ray, depth - 1);

也适用于非余弦部分:

代码语言:javascript
复制
pdf = 1.0/(2.0*PI);
return attenuation/pdf * ray_trace(scattered_ray, depth - 1);

如果您想使用非余弦估计,那么您将不得不使用余弦分布抽样。它看起来是这样的:

代码语言:javascript
复制
Vec3 Lambertian::scatter_cosine_dist(Ray ray, Intersection intersection, Ray &scattered_ray)
{
    double phi = random(0.0, 2.0 * PI);
    double sin_phi = sine(phi);
    double cos_phi = cosine(phi);

    double cos_theta = random(-1.0, 1.0);
    double sin_theta = sqrt(1 - cos_theta * cos_theta);

    Vec3 scattered_direction = Vec3(sin_phi * sin_theta, cos_phi * sin_theta, cos_theta).normalize();

    scattered_ray.origin = intersection.hit_point;
    scattered_ray.direction = (intersection.normal+scattered_direction).normalize();

    return this.albedo;
}

然后也修改非余弦估计器的pdf:

代码语言:javascript
复制
pdf_wo_cos = 1.0/PI;
return attenuation/pdf_wo_cos * ray_trace(scattered_ray, depth - 1);

这里面的pdf实际上是cos(theta)/PI,但是余弦与呈现方程中的余弦相抵消。如果对不带余弦的估计器采用余弦分布抽样,而对具有余弦的估计器采用均匀抽样,则应得到与噪声相等的结果(余弦估计器应产生较少的噪声)。

票数 1
EN

Computer Graphics用户

发布于 2022-06-21 11:03:11

你为intersection.normal和scattered_ray.direction使用了什么坐标系?一种典型的方法是在局部空间中采样散射方向,然后将其转化为世界空间。因此,余弦θ将在采样函数中计算。我不确定是否是坐标系引起了你们的问题。

票数 1
EN
页面原文内容由Computer Graphics提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://computergraphics.stackexchange.com/questions/12700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档