【Ray Tracing in One Weekend 超详解】 光线追踪1-9 景深
今天我们来学最后一章
Chapter11:Defocus Blur

Preface
散焦模糊 也称 景深
首先,我们来了解一下散焦模糊,我们在真实相机中散焦模糊的原因是因为它们需要一个大圈(而不仅仅是一个针孔)来聚光。这会使所有东西都散焦,但是如果用小孔的话,那么通过前后调整相机镜头,就会使得一切景色都会聚焦到相机镜头中,也就是会汇聚到那个孔内。物体聚焦的那个平面的距离由镜头和胶片/传感器之间的距离控制。这就是为什么当你改变焦点时可以看到镜头相对于相机移动的原因。
光圈是一个可以有效控制镜头大小的孔。对于真正的相机,如果你需要更多光线,你可以使光圈更大,同时也会获得更多的散焦模糊。对于我们的虚拟相机,我们也需要一个光圈
真正的相机具有复杂的复合镜头。对于我们的代码,我们可以模拟顺序:传感器,然后是镜头,然后是光圈,并找出发送光线的位置并在计算后翻转图像(图像在胶片上倒置投影)。人们通常使用薄透镜模拟近似。
引用书上一张图(相机聚焦成像)

我们不需要这么复杂,我们通常从镜头表面开始射线,并将它们发送到虚拟胶片平面,方法是找到胶片在焦点平面上的投影(在距离focus_dist处)。
正文
前面说了一大堆,看着比较复杂,其实并没有那么难
前言说了三件事情:
第一点,生活中的相机成像分为两个部分,inside和outside,涉及3个物:film(胶片)、lens(镜片)、focusPlane(焦点平面),而我们只需要outside部分

其次第二点,我们的眼睛(或者相机)不再是一个点而是眼睛所在的周围圆盘上的随机点,因为实际的相机是有摄像镜头的,摄像镜头是一个大光圈(很大一个镜片),并不是针孔类的东东,所以,我们要模拟镜头,就要随机采针孔周围的光圈点。
可能有人不明白这里,可以回去看看1-3
看一下这张图

这是之前我们讲的光线追踪的成像过程,从eye开始发射视线,这个扫描屏幕中的每个点,如果中间被物体遮挡,那么计算,计算之后的像素值为屏幕上该点的像素值,如果没有遮挡,那么屏幕上那个点的像素值就是背景对应的值
我们这里只不过是把eye变为周围单位圈内的随机点,仅此模拟实际相机镜头
第三点,这个应该是上一章节提到的问题:
上一章节我们说了,为了方便,上一章节假定成像平面位于z = -1(或者是-w平面,按w基向量算)
所以 tan(theta/2) = (h/2) / dis ,其中dis为1
而这一章,我们使dis真正变成了一个变量,即:焦距(镜片到成像平面之间的距离)
(图片来自百度百科:
)
随之,我们的成像平面也就到了z = -focus,或者是-focus * w平面(按w基向量算)
所以,构造函数,我们就需要加两个参数,改两行行即可

还有就是单位圆盘取随机点函数
const rtvec random_unit_disk() //find a random point in unit_disk
{
rtvec p;
do
{
p = 2.0*rtvec(rtrand01(), rtrand01(), 0) - rtvec(, , );
} while (dot(p, p) >= 1.0);
return p;
}
下面是所有的camera类
/// camera.h // -----------------------------------------------------
// [author] lv
// [begin ] 2019.1
// [brief ] the camera-class for the ray-tracing project
// from the 《ray tracing in one week》
// ----------------------------------------------------- #ifndef CAMERA_H
#define CAMERA_H #include "ray.h" namespace rt
{ class camera
{
public:
camera(rtvec lookfrom, rtvec lookat, rtvec vup, rtvar vfov, rtvar aspect, rtvar aperture, rtvar focus)
:_eye(lookfrom)
,_lens_radius(aperture/)
{
rtvar theta = vfov * π / ;
rtvar half_height = tan(theta / ) * focus; //tan(theta/2) = (height/2) / 焦距
rtvar half_width = aspect * half_height;
_w = (lookfrom - lookat).ret_unitization();
_u = cross(vup, _w).ret_unitization();
_v = cross(_w, _u); //向量运算
_start = _eye - half_width * _u - half_height * _v - focus * _w;//高和宽都乘了焦距,w也要乘,不然公式是错的
_horizontal = * half_width * _u;
_vertical = * half_height * _v;
} inline const ray get_ray(const rtvar u,const rtvar v)const
{
rtvec rd = _lens_radius * random_unit_disk();
rtvec offset = _u * rd.x() + _v * rd.y();
return ray{ _eye + offset, _start + u*_horizontal + v*_vertical - (_eye + offset) };
} inline const ray get_ray(const lvgm::vec2<rtvar>& para)const
{ return get_ray(para.u(), para.v()); } inline const rtvec& eye()const { return _eye; } inline const rtvec& start()const { return _start; } inline const rtvec& horizontal()const { return _horizontal; } inline const rtvec& vertical()const { return _vertical; } inline const rtvec& u()const { return _u; } inline const rtvec& v()const { return _v; } inline const rtvec& w()const { return _w; } inline const rtvar lens_r()const { return _lens_radius; } private:
rtvec _u; rtvec _v; rtvec _w; rtvec _eye; rtvec _start; //left-bottom rtvec _horizontal; rtvec _vertical; rtvar _lens_radius; //the radius of lens }; } #endif
camera.h
所以,我们用上一章的球体设置,把相机改一下,渲染一把

渲染效果就是开篇那张图
晚安
【Ray Tracing in One Weekend 超详解】 光线追踪1-9 景深的更多相关文章
- 【Ray Tracing The Next Week 超详解】 光线追踪2-9
我们来整理一下项目的代码 目录 ----include --hit --texture --material ----RTdef.hpp ----ray.hpp ----camera.hpp ---- ...
- 【Ray Tracing The Next Week 超详解】 光线追踪2-6 Cornell box
Chapter 6:Rectangles and Lights 今天,我们来学习长方形区域光照 先看效果 light 首先我们需要设计一个发光的材质 /// light.hpp // ------- ...
- 【Ray Tracing in One Weekend 超详解】 光线追踪1-4
我们上一篇写了Chapter5 的第一个部分表面法线,那么我们来学剩下的部分,以及Chapter6. Chapter5:Surface normals and multiple objects. 我们 ...
- 【Ray Tracing The Next Week 超详解】 光线追踪2-7 任意长方体 && 场景案例
上一篇比较简单,很久才发是因为做了一些好玩的场景,后来发现这一章是专门写场景例子的,所以就安排到了这一篇 Preface 这一篇要介绍的内容有: 1. 自己做的光照例子 2. Cornell box画 ...
- 【Ray Tracing The Next Week 超详解】 光线追踪2-8 Volume
Preface 今天有两个东东,一个是体积烟雾,一个是封面图 下一篇我们总结项目代码 Chapter 8:Volumes 我们需要为我们的光线追踪器添加新的物体——烟.雾,也称为participat ...
- 【Ray Tracing The Next Week 超详解】 光线追踪2-5
Chapter 5:Image Texture Mapping 先看效果: 我们之前的纹理是利用的是撞击点p处的位置信息,比如大理石纹理 而我们今天的图片映射纹理采用2D(u,v)纹理坐标来进行. 在 ...
- 【Ray Tracing in One Weekend 超详解】 光线追踪1-8 自定义相机设计
今天,我们来学习如何设计自定义位置的相机 ready 我们只需要了解我们之前的坐标体系,或者说是相机位置 先看效果 Chapter10:Positionable camera 这一章我们直接用概念 ...
- 【Ray Tracing The Next Week 超详解】 光线追踪2-4 Perlin noise
Preface 为了得到更好的纹理,很多人采用各种形式的柏林噪声(该命名来自于发明人 Ken Perlin) 柏林噪声是一种比较模糊的白噪声的东西:(引用书中一张图) 柏林噪声是用来生成一些看似杂乱 ...
- 【Ray Tracing The Next Week 超详解】 光线追踪2-3
Preface 终于到了激动人心的纹理章节了 然鹅,看了下,并不激动 因为我们之前就接触过 当初有一个 attenuation 吗? 对了,这就是我们的rgb分量过滤器,我们画出的红色.蓝色.绿色等 ...
- 【Ray Tracing The Next Week 超详解】 光线追踪2-2
Chapter 2:Bounding Volume Hierarchies 今天我们来讲层次包围盒,乍一看比较难,篇幅也多,但是咱们一步一步来,相信大家应该都能听懂 BVH 和 Perlin text ...
随机推荐
- node.js 开发简易的小爬虫
node.js 开发简易的小爬虫 最近公司开发一款医药类的软件,所以需要一些药品的基础数据,所以本人就用node.js写一个简易的小爬虫,并写记录这个Demo以供大家参考. 一.开发前的准备: 1, ...
- python常用模块-调用系统命令模块(subprocess)
python常用模块-调用系统命令模块(subprocess) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. subproces基本上就是为了取代os.system和os.spaw ...
- 什么是spu和sku
电商概念SPU与SKU SPU = Standard Product Unit (标准产品单位)SPU是商品信息聚合的最小单位,是一组可复用.易检索的标准化信息的集合,该集合描述了一个产品的特性.通俗 ...
- 【DS】排序算法之快速排序(Quick Sort)
一.算法思想 快速排序,顾名思义,效率比较于其他算法,效率比较高.<算法导论>也专门对其进行讲解.其算法设计使用分治思想,如下: 1)从数组A[p...r]中选择一个元素,将数组划分成两个 ...
- python学习笔记6--操作redis
一.redis操作 import redis r=redis.Redis(host='211.149.218.16',port=6379,password='123456',db=2) r.set(' ...
- HTML5 拖拽实现
简介: 最早在网页中引入JavaScript拖放功能是IE4.当时,网页中只有两种对象可以拖放:图像和某些文本.拖放图像时,把鼠标放到图像上,按住鼠标不放就可以拖放它.拖放文本时,要先选中文本,然后可 ...
- jdk1.8.0_45源码解读——Map接口和AbstractMap抽象类的实现
jdk1.8.0_45源码解读——Map接口和AbstractMap抽象类的实现 一. Map架构 如上图:(01) Map 是映射接口,Map中存储的内容是键值对(key-value).(02) A ...
- HDU 4508 湫湫系列故事——减肥记I (完全背包)
题意:有n种食物,每种食物可以给湫湫带来一个幸福感a,同时也会给她带来b的卡路里的摄入,然后规定她一天摄入的卡路里的量不能超过m,一共有n种食物,问可以得到的 最大的幸福感是多少? 解题报告:一开始以 ...
- 判断gps是否在国内
参考文章:[WP7]判断GPS坐标是否在中国 根据国家行政边界判定(光线投射算法) 按需求调整了原文中的部分边界值,测试几组边界附近内外坐标,结果较为准确. /** * 判断GPS坐标是否在多边形中 ...
- Python 优雅获取本机 IP 方法
原文 见过很多获取服务器本地IP的代码,个人觉得都不是很好,例如以下这些 不推荐:靠猜测去获取本地IP方法 #!/usr/bin/env python # -*- coding: utf-8 -*- ...