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(, , , , , 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 < && info._materialp->scatter(sight, info, albedo, scattered, pdf))
{
rtvec on_light = rtvec( + lvgm::rand01() * ( - ), , + lvgm::rand01() * ( - ));
rtvec to_light = on_light - info._p;
double distance_squared = to_light.squar();
to_light.self_unitization();
if (dot(to_light, info._n) < )
return emitted;
double light_area = ( - )*( - );
double light_cosine = fabs(to_light.y());
if (light_cosine < 1e-)
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 + ) / 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())<.)
return _emit->value(u, v, p);
else
return rtvec();
}

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

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

没什么大的变化

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

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

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

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

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

  1. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-7 混合概率密度

     Preface 注:鉴于很多网站随意爬取数据,可能导致内容残缺以及引用失效等问题,影响阅读,请认准原创网址: https://www.cnblogs.com/lv-anchoret/category ...

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

     Preface 往后看了几章,对这本书有了新的理解 上一篇,我们第一次尝试把MC积分运用到了Lambertian材质中,当然,第一次尝试是失败的,作者发现它的渲染效果和现实有些出入,所以结尾处声明要 ...

  3. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-4 基于重要性采样的材质初探

     Preface 我们今天来把第三本书从开局到现在讲的一大堆理论运用到我们的框架中,那么今天我们首先将原始的材质改为基于重要性采样原理的材质 这一篇是代码工程中进行MC理论应用的初步尝试篇  Read ...

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

    开学人倍忙,趁着第二周周末,我们继续图形相关的博客  Preface 今天我们来介绍一些理论方面的东西,为Monte Carlo 应用到我们的光线追踪器做铺垫 我们今天会介绍两章的东西,因为有一章内容 ...

  5. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-2 蒙特卡罗(二) 重要性采样

    书本内容:见相册 preface 还记的我们上一篇说的Monte Carlo 维度诅咒吗 上一篇算是二维的例子吧,大家看了之后是否想着写一个一维的Monte Carlo模拟积分?(我想了,没写出来) ...

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

    今天起,我们就开始学习第三本书了 这本书主要讲的是蒙特卡罗渲染,以及相关的数学.术语概念等 这本书相较于前面两本有着什么不同,承担着什么样的任务,尚涉书未深,姑妄言之: 第一本书,带领我们初探光线追踪 ...

  7. html5的float属性超详解(display,position, float)(文本流)

    html5的float属性超详解(display,position, float)(文本流) 一.总结 1.文本流: 2.float和绝对定位都不占文本流的位置 3.普通流是默认定位方式,就是依次按照 ...

  8. HTML中DOM核心知识有哪些(带实例超详解)

    HTML中DOM核心知识有哪些(带实例超详解) 一.总结: 1.先取html元素,然后再对他进行操作,取的话可以getElementById等 2.操作的话,可以是innerHtml,value等等 ...

  9. Mysql超详解

    Mysql超详解 一.命令框基本操作及连接Mysql 找到Mysql安装路径,查看版本 同时按快捷键win+R会弹出一个框,在框中输入cmd 点击确定后会出现一个黑框,这是命令框,我们的操作要在这命令 ...

随机推荐

  1. Confluence 6 SQL Server 数据库驱动修改

    从 Confluence 6.4 开始,我们使用官方的 Microsoft SQL Server JDBC 驱动来替换掉开源的 jTDS 驱动.从这个版本开始所有的安装都会默认使用官方的 Micros ...

  2. 开源中国社区 https://git.oschina.net/ 添加 SSH 公钥 添加

    首先可以参考官方的帮助文档 http://git.mydoc.io/?t=154712 然后进去码云首页 http://git.oschina.net 然后找到右边的头像点击一下  然后点击修改资料 ...

  3. 使用Navicat快速生成数据库字典

    https://blog.csdn.net/maquealone/article/details/60764420

  4. git bash here 的 ~/.bashrc 配置文件。和 vue/cli 3. 0 的 .vuerc文件(preset )

    今天就来讲一下git有关的小技巧,.bashrc文件是用户配置文环境变量的文件,每次git bash会首先运行里面的内容 1.自动运行 每次进入git bash都会先读取.bashrc里面的内容,因此 ...

  5. linux下mysql源码安装

    参考链接:http://blog.csdn.net/zqtsx/article/details/9378703 下载mysql安装包, 不会下载点这里 地址:ftp://mirror.switch.c ...

  6. linux 压缩和解压缩

    压缩 tar -cvf jpg.tar *.jpg //将目录里所有jpg文件打包成tar.jpg tar -czf jpg.tar.gz *.jpg   //将目录里所有jpg文件打包成jpg.ta ...

  7. C/C++字节序(大端/小端)判断

    C/C++大端小端判断 说的是变量的高字节.低字节在内存地址中的排放顺序. 变量的高字节放到内存的低地址中(变量的低字节放到内存的高地址中)==>大端 变量的高字节放到内存的高地址中(变量的低字 ...

  8. 为tomcat8安装Native library

    安装依赖包 yum install -y cmake gcc expat-devel perl wget 安装apr wget http://mirrors.hust.edu.cn/apache//a ...

  9. php让一个数组按照另外一个数组的键名进行排序

    $a = [ 'id', 'name', 'identityId', 'phone', 'email', 'schoolId' ]; $b = [ 'id' => '唯一标识', 'identi ...

  10. 有关centos7 图形化root用户登录

    好久不用的虚拟机开机后,是图形化登录界面,原来是命令行界面,后来安装和图形化 结果使用我记录的root密码死活登录不了,心想是不是时间久了忘记了root密码 然后开始尝试各种单用户修改root密码,再 ...