【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-6 直接光源采样

Chapter7 Sample Lights Directly

 Preface

今天我们来讲这个还算牛逼的技术——直接光源采样

之前我们提到过,在2-7

前两篇我们也提到要减少噪点,就是图片上的黑点点,所以,所有的矛头都指向了这一篇。

简单说一下为什么会有那么多小点点,就是因为光线路径中没有触碰到光源,路径计算之后就会是黑色的点,可以通过发射大量的光线,比如计算每个像素点的时候发射8k~1w条采样光线进行路径计算;也可以路径计算方面做文章,比如加深路径计算递归深度;等等诸如此类。但是上述方法都是暴力解决法,相当耗时,我们可以运用数学对其进行优化,从而实现画质和效率的双面提升,这就是我们今天要讲的——直接光源采样!

 Ready

可能您需要以下基础:

1.微分

2.立体角 (蒙特卡罗(三))

没了,剩下全靠想象

 content

简明扼要。

我们朝光源方向发送光线或者生成朝向光源的随机方向都是很容易实现的,但是我们需要知道的是,pdf(direction)是什么呢?

引用书上一张图:

对于一个光源区域A,如果我们均匀采样该区域,那么这个pdf就等于1/A,意思就是每个点的概率均等

但是和我们的单位球体结合在一起的话,就比较麻烦了,见上图

?为什么老是提到单位球体呢??

因为我们的光线和物体表面的交点,会作为下一个eye,然后新的视线方向是表面单位球随机产生的方向,具体见1-5中的diagram7-3

好了,渊源就是酱紫,我们继续

如果那个小的微分区域dA的采样概率为

  p_q(q)*dA(采样比例乘以微分区域),也就是dA/A

而对应到单位球体表面的很小的区域,即我们所述的方位角。方位角微分dΩ对应的采样概率为

  p(direction)*dΩ

这里有一个用来描述dΩ 和 dA 的表达式:

= dA cosα / (distance(p,q^2)

即:方位角微分区域:光源微分区域分成(球心到A中心距离平方)份,取其中的cosα代表的份额数

因为这个dA 和 dΩ的概率是相同的,所以就有如下等式

p(direction) * cosα * dA / (distance(p,q)^2) = p_q(q) * dA = dA / A

所以

p(direction) = distance(p,q)^2 / (cosα * A)

我们接下来就检验一下这个数学公式是否正确

但是代码可能非常丑

我们需要之前的光源的区域参数

    list[cnt++] = new xz_rect(200, 350, 220, 340, 550, light);

所以我们有以下的代码

rtvec lerp(const ray& sight, intersect* world, int depth)
{
    hitInfo info;
    if (world->hit(sight, (rtvar)0.001, rtInf(), info))
    {
        ray scattered;
        rtvec emitted = info._materialp->emitted(info._u, info._v, info._p);
        rtvar pdf;
        rtvec albedo;
        if (depth < 50 && info._materialp->scatter(sight, info, albedo, scattered, pdf))
        {
            rtvec on_light = rtvec(213 + lvgm::rand01() * (343 - 213), 554, 227 + lvgm::rand01() * (332 - 227));
            rtvec to_light = on_light - info._p;
            double distance_squared = to_light.squar();
            to_light.self_unitization();
            if (dot(to_light, info._n) < 0)
                return emitted;
            double light_area = (343 - 213)*(332 - 227);
            double light_cosine = fabs(to_light.y());
            if (light_cosine < 1e-6)
                return emitted;
            pdf = distance_squared / (light_cosine*light_area);
            scattered = ray(info._p, to_light, sight.time());
            return emitted + albedo *info._materialp->scatter_pdf(sight, info, scattered)*lerp(scattered, world, depth + 1) / pdf;
        }
        else
            return emitted;
    }
    else
        return rtvec();
}

如下图:

因为我们一路做测试,做图形分析对比,所以我们上图是sample为250时候的效果

据说,sample为10时,效果依旧很好

所以又超快速运行了一个sample为10的

不管怎样,我们的图形噪点已经做到了比较不错的境地了,sample为10!!!

再看看之前的sample为250的图形效果

简直噪出天际线

关于本篇的那个图

天花板上灯光周围的噪声是由于灯光是双面的,灯光和天花板之间有一个狭窄空间。

我们可以通过将灯光法向量调至垂直向下来解决这一问题,同时让我们的灯光发射函数也做相应的处理

    virtual rtvec emitted(const ray& rIn, const hitInfo& info, const rtvar u, rtvar v, const rtvec& p)const
        {
        if(dot(info._n,rIn.direction())<0.)
            return _emit->value(u, v, p);
        else
            return rtvec();
        }

记得一起改了material基类,以及lerp的emit函数调用根据上述参数描述

所以我们又得到了一个sample为10的新图

没什么大的变化

只是灯光周围的噪点少了,解释:

因为灯光的法向量垂直向下,而我们的反射光线与反射之后与法向量的夹角为锐角的时候才进行纹理计算

而来自屋顶上面的光线与灯光区域碰撞反射的方向与法向量呈钝角(注意是反射之后的新方向不是入射光方向)则不计算返回黑色,默认光无法到达

感谢您的阅读,生活愉快~

原文地址:https://www.cnblogs.com/lv-anchoret/p/10534492.html

时间: 2024-10-09 16:36:55

【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-6 直接光源采样的相关文章

【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-5 random direction &amp; ONB

 Preface 往后看了几章,对这本书有了新的理解 上一篇,我们第一次尝试把MC积分运用到了Lambertian材质中,当然,第一次尝试是失败的,作者发现它的渲染效果和现实有些出入,所以结尾处声明要通过实践,改进当前的效果 于是乎,就有了后面的章节,几乎整本书都在讲,如何一步一步地改进上一篇的画质,使其更加符合现实,上一篇其实是抛砖引玉 这本书的小标题名为the rest of your life 通过前面几章,我们可以更好地理解这句话:我们通过MC积分优化效果,采用的是pdf函数,之前说过,

【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-1

今天起,我们就开始学习第三本书了 这本书主要讲的是蒙特卡罗渲染,以及相关的数学.术语概念等 我们先来一个简单的开胃菜 chapter 1:A Simple Monte Carlo Program 蒙特卡罗方法(MC)是一种统计模拟方法,是一类很重要的数值计算方法,它是一种使用随机数解决好很多实际问题的方法. 先来看一个很简单的例子:估计π 有很多经典的方法,其中之一是 假设你扔了很多随机的点到方框中,那么有一部分在圆内,其中圆内点和方框点的比例应该就是圆的面积和方框面积的比例,由此: 比例 =

【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-3 蒙特卡罗 (三)

开学人倍忙,趁着第二周周末,我们继续图形相关的博客  Preface 今天我们来介绍一些理论方面的东西,为Monte Carlo 应用到我们的光线追踪器做铺垫 我们今天会介绍两章的东西,因为有一章内容太过简单 本篇目的原版内容 见相册 这个东西你点上去会有页数的,不要看混了  ready 看这一篇您需要具备以下知识 1. 了解重要性采样 2. 二重积分,基础微分 3. (半)球坐标系 4. 光线追踪基本原理 5. 立体角(solid angle),现在普及一下 首先类比二维空间的圆,假设我们在二

POJ 1659 Frogs&#39; Neighborhood(可图性判定—Havel-Hakimi定理)【超详解】

Frogs' Neighborhood Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 9897   Accepted: 4137   Special Judge Description 未名湖附近共有N个大小湖泊L1, L2, ..., Ln(其中包括未名湖),每个湖泊Li里住着一只青蛙Fi(1 ≤ i ≤ N).如果湖泊Li和Lj之间有水路相连,则青蛙Fi和Fj互称为邻居.现在已知每只青蛙的邻居数目x1, x2, ..

CentOS6启动过程超详解分析

CentOS 6 开机流程--linux由kernel和rootfs组成.kernel负责进程管理.内存管理.网络管理.驱动程序.文件系统.安全等;rootfs由程序和glibc组成,完善操作系统的功能.同时linux内核的特点是模块化,通过对模块装载卸载可以对内核功能自定义.linux内核文件:/boot/vmlinuz-2.6.32-696.el6.x86_64 整体的流程 BIOS/开机自检 MBR引导(Boot Loader) 启动内核 启动第一个进程init 一.BIOS/开机自检 1

【Ray Tracing in One Weekend 超详解】 光线追踪1-10

<Ray Tracing in One Weekend>完结篇 最近课程上机实验,封面图渲染时间也超长,所以写东西就落下了,见谅 这篇之后,我会继续<Ray Tracing The Next Week>,还请多多关注 这几天我在渲染这本书的封面图,封面图还没出,不算结束,刚好安排了10节 今天呢,有两件事: 1.阐述整个工程的文件组织即内容 2.阐述封面,完结 12.1工程文件组织 试过很多方法,问过很多老师,无奈,子类继承实现的父类纯虚函数实在无法和类声明分成两个文件(即声明放于

【Ray Tracing The Next Week 超详解】 光线追踪2-3

 Preface 终于到了激动人心的纹理章节了 然鹅,看了下,并不激动 因为我们之前就接触过 当初有一个 attenuation 吗? 对了,这就是我们的rgb分量过滤器,我们画出的红色.蓝色.绿色等等,都是通过它来控制的 专业点的词语叫做rgb衰减比例,比如rtvec(1.,0.,0.),最后呈现出来的是红色,因为r保留了100% 它是怎么控制的呢,我们来回顾一下这个过程 首先,我们创建一个材质球 后面那个rtvec(0.4,0.2,0.1)就是衰减比例(衰减到原来的百分之..) 之后 进入数

【Ray Tracing The Next Week 超详解】 光线追踪2-6 Cornell box

Chapter 6:Rectangles and Lights 今天,我们来学习长方形区域光照  先看效果 light 首先我们需要设计一个发光的材质 /// light.hpp // ----------------------------------------------------- // [author] lv // [begin ] 2019.1 // [brief ] the areaLight-class for the ray-tracing project // from t

【Ray Tracing The Next Week 超详解】 光线追踪2-7 任意长方体 &amp;&amp; 场景案例

上一篇比较简单,很久才发是因为做了一些好玩的场景,后来发现这一章是专门写场景例子的,所以就安排到了这一篇 Preface 这一篇要介绍的内容有: 1. 自己做的光照例子 2. Cornell box画质问题及优化方案 3. 新的场景几何体——长方体 轴平行长方体 任意长方体 我们这一篇重实践轻理论阐述 ready 1. 需要上一章的知识 但是,上一章的Cornell box画质优化仅限于盒子本身,如果作为场景和其他物体放在一起就不能那么优化画质 即,Cornell box像素计算失败应该返回黑色