【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 的表达式:
dΩ = 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 直接光源采样的更多相关文章
- 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-7 混合概率密度
Preface 注:鉴于很多网站随意爬取数据,可能导致内容残缺以及引用失效等问题,影响阅读,请认准原创网址: https://www.cnblogs.com/lv-anchoret/category ...
- 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-5 random direction & ONB
Preface 往后看了几章,对这本书有了新的理解 上一篇,我们第一次尝试把MC积分运用到了Lambertian材质中,当然,第一次尝试是失败的,作者发现它的渲染效果和现实有些出入,所以结尾处声明要 ...
- 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-4 基于重要性采样的材质初探
Preface 我们今天来把第三本书从开局到现在讲的一大堆理论运用到我们的框架中,那么今天我们首先将原始的材质改为基于重要性采样原理的材质 这一篇是代码工程中进行MC理论应用的初步尝试篇 Read ...
- 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-3 蒙特卡罗 (三)
开学人倍忙,趁着第二周周末,我们继续图形相关的博客 Preface 今天我们来介绍一些理论方面的东西,为Monte Carlo 应用到我们的光线追踪器做铺垫 我们今天会介绍两章的东西,因为有一章内容 ...
- 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-2 蒙特卡罗(二) 重要性采样
书本内容:见相册 preface 还记的我们上一篇说的Monte Carlo 维度诅咒吗 上一篇算是二维的例子吧,大家看了之后是否想着写一个一维的Monte Carlo模拟积分?(我想了,没写出来) ...
- 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-1 蒙特卡罗 (一)
今天起,我们就开始学习第三本书了 这本书主要讲的是蒙特卡罗渲染,以及相关的数学.术语概念等 这本书相较于前面两本有着什么不同,承担着什么样的任务,尚涉书未深,姑妄言之: 第一本书,带领我们初探光线追踪 ...
- html5的float属性超详解(display,position, float)(文本流)
html5的float属性超详解(display,position, float)(文本流) 一.总结 1.文本流: 2.float和绝对定位都不占文本流的位置 3.普通流是默认定位方式,就是依次按照 ...
- HTML中DOM核心知识有哪些(带实例超详解)
HTML中DOM核心知识有哪些(带实例超详解) 一.总结: 1.先取html元素,然后再对他进行操作,取的话可以getElementById等 2.操作的话,可以是innerHtml,value等等 ...
- Mysql超详解
Mysql超详解 一.命令框基本操作及连接Mysql 找到Mysql安装路径,查看版本 同时按快捷键win+R会弹出一个框,在框中输入cmd 点击确定后会出现一个黑框,这是命令框,我们的操作要在这命令 ...
随机推荐
- Confluence 6 Confluence 安装目录
Confluence 安装的目录(Confluence Installation directory)定义的是 Confluence 是在那里进行安装的.这个目录有时候也被称为 Confluence ...
- Confluence 6 审查日志的对象
审查日志记录一下事件的信息,这个记录不是详细的信息列表.但是这些信息能够让你了解你能够在日志中看到些什么内容. 空间 创建和删除一个空间. 编辑空间细节,主题,配色方案或者样式表. 修改空间权限,包括 ...
- Confluence 6 禁用管理员联系表单
如果你希望禁用这个功能,不允许用户通过发送电子邮件的方式联系站点管理员.你可以禁用这个页面中有关输入用户信息发送电子邮件的部分.你只能禁用用户电子邮件输入表单,如果你按照上面描述的步骤在 'Custo ...
- 高并发编程基础Synchronized与Volatile
关键字Synchronized: 当使用Synchrnized (o) ,锁定 o 的时候,锁定的是 o 指向的堆内存中 new 出来的对象,而非 o 引用,当锁定 o 以后,一旦 o 指向了其他对象 ...
- js获取到的页面中的checkbox选中的项
需求描述:列表第一列是checkbox name和value都是id 想通过复选框的勾选状态来获取id,在js中获取 js代码: var checkId=$("input[name='che ...
- samba 二进制包 tar.gz 安装
一.下载 sudo wget https://download.samba.org/pub/samba/stable/samba-4.8.10.tar.gz 二.解压 sudu tar -xvzf s ...
- tensorflow(4):神经网络框架总结
#总结神经网络框架 #1,搭建网络设计结构(前向传播) 文件forward.py def forward(x,regularizer): # 输入x 和正则化权重 w= b= y= return y ...
- MySQL is running but PID file could not be found(解决方法)
启动MySQL时报错: [root@xzw /]# service mysqld status MySQL is running but PID file could not be found ...
- spring cloud 路由网关zuul的高可用
Zuul的高可用非常关键,因为外部请求到后端微服务的流量都会经过Zuul.故而在生产环境中,我们一般都需要部署高可用的Zuul以避免单点故障. 笔者分两种场景讨论Zuul的高可用. Zuul客户端也注 ...
- jenkins卡在等待界面解决方法
1.安装jenkins最新版的时候,发现一直卡在等待界面上 如图显示: 原因:jenkins里面文件指向国外的官网,因为防火墙的原因连不上 解决方法:将配置文件里面的url换成国内的即可