【Ray Tracing in One Weekend 超详解】 光线追踪1-2
今天我们开始进入正篇
Chapter 3: Rays, a simple camera, and background
对于所有的光线追踪器,基本都有一个光线类,计算沿光线看到的颜色。
我们的光线是一个矢量运算:
p(t) = a + t * b.
书中的向量用大写粗体字表示,但这里我遵循一般表示法:矩阵为粗体大写字母,向量为粗体小写字母,而标量为正常字体
P是光线指向的目标位置,a是光线的起点,b是光线指向的方向,t则是光线步长。
如图:

我们如下定义ray-class
/// ray.h // -----------------------------------------------------
// [author] lv
// [begin ] 2018.12
// [brief ] the ray-class for the ray-tracing project
// from the 《ray tracing in one week》
// ----------------------------------------------------- #ifndef RAY_H
#define RAY_H #include <lvgm\type_vec\type_vec.h> //https://www.cnblogs.com/lv-anchoret/p/10163085.html class ray
{
public: using value_type = lvgm::precision; using vec_type = lvgm::vec3<value_type>; public:
ray()
:_a{vec_type()}
, _b{vec_type()}
{ } ray(const vec_type& a, const vec_type& b)
:_a(a)
,_b(b)
{ } ray(const ray& r)
:_a(r._a)
,_b(r._b)
{ } inline vec_type origin()const { return _a; } inline vec_type direction()const { return _b; } inline vec_type go(const value_type t)const { return _a + t * _b; } private:
vec_type _a; vec_type _b; }; #endif //ray_h
然后我们来看制作一个光线追踪器,它的核心在于,发送光线去穿过像素,进而计算出沿着光线方向,什么颜色被看到了
我们看到物体,是外部光照射到物体表面,经过表面反射之后,那部分反射进入眼睛的光被我们捕捉,从而看到了光来源位置的物体,那么,我们假设从眼睛发射一束光,它代表我们的视线,当它沿着某个方向一直向前,视线会与物体表面相交,那么,我们就捕捉到了一个像素。光线追踪器就是计算视线的一种形式。
为了更贴切,我们在此之后将光线统一称为视线。
它可以计算视线与表面交点以及交点处的颜色。
上述内容会在后续的案例讲解过程中逐步理解的。
现在,我们来了解一下本书采用的默认坐标系统

coord 1.1
坐标(0,0,0)处为我们的眼睛(或者相机),我们的绘图区域为蓝色框代表的矩形平面,也就是你观察图像的那个屏幕。
按照学OpenGL的老规矩,第一堂当然是线性插值
差值公式:
blended_value = (1-t) * start_value + t * end_value
解释一下上面的公式:
t 是一个系数,根据情况确定,将开始颜色和终止颜色进行比例混合,然后得到混合色
如果我们要做一个从白色到蓝色根据坐标位置确定混合比例进行插值的矩形彩图
我们该如何做呢?
第一步,我们需要确定分辨率,假定为400*200,就用coord1.1的坐标体系去做。
第二步,我们需要确定开始位置和终止位置,假定从左下角混合到右上角,混合颜色为白色和蓝色。
第三步,我们需要确定视线,即确定从眼睛出发到屏幕的向量
1. 确定在平面中的位置,从左下角开始每一个平面位置均由水平和垂直两个分向量叠加而成:

diagram 3-1
由坐标系统得知,lower-left的坐标为(-2,-1,-1)
若y =(0,0.5,0),x =(1,0,0),则pos =(-1,-0.5,-1)
2.当我们确定了pos之后,其实,视线已经确定好了,因为眼睛的坐标为(0,0,0),pos即为视线向量
第四步,我们需要从分辨率到屏幕做一个映射。
看图还记得我们的分辨率是400*200吗,而屏幕的范围是4*2的矩形
所以,我们需要做一个映射,和上次一样,我们可以将分辨率下的位置通过除法转换到标准坐标,然后再通过标准坐标转换到屏幕坐标
例如一个分辨率下的x的步长为388,首先通过388/400变为一个0~1的实数,然后乘以4,即可变为屏幕步长
然后通过diagram 3-1,确定屏幕中的位置
第五步,我们需要确定比例系数t,我们可以选择x或y方向的其中一个做映射。
因为屏幕坐标系不确定,我们采用的是4*2的,但不是铭文规定的,所以我们需要将视线向量(等同于pos坐标位置)进行单位化,这样的话就可以把每个坐标分量的长度控制在[-1, 1],如果我们把它+1再除以2,那么就完全转化到[0, 1]了,此时,每个坐标方向的分向量范数均为[0, 1],它们是由三个坐标基共同作用而成的独一无二的,所以,你可以采用x的单位化值作为t,也可以把y作为t。
第六步,经过上述一顿操作,我们终于得到了屏幕某个点对应的blend_value,颜色混合值(或称为插值)
至此,我们基于位置进行的颜色插值就讲解完了
下面是代码:
#define LOWPRECISION #include <fstream>
#include "ray.h"
using namespace lvgm; #define stds std:: ray::vec_type lerp(const ray& r)
{
ray::vec_type unit_dir = r.direction().ret_unitization(); //单位化
ray::value_type t = 0.5*(unit_dir.y() + 1.0); //将y分量映射到[0, 1]
//插值公式 白色&蓝色
return (1.0 - t)*ray::vec_type(1.0, 1.0, 1.0) + t*ray::vec_type(0.0, 0.0, 1.0);
} void build_3_1()
{
int X = , Y = ; //分辨率 400*200
stds ofstream file("graph3-1.ppm");
if (file.is_open())
{
file << "P3\n" << X << " " << Y << "\n255\n";
ray::vec_type left_bottom{ -2.0,-1.0,-1.0 }; //左下角作为开始位置
ray::vec_type horizontal{ 4.0,, }; //屏幕水平宽度
ray::vec_type vertical{ ,2.0, }; //屏幕垂直高度
ray::vec_type eye{ ,, }; //眼睛位置
for (int j = Y - ; j >= ; --j)
for (int i = ; i < X; ++i)
{
vec2<ray::value_type> para(ray::value_type(i) / X, ray::value_type(j) / Y);
ray r(eye, left_bottom + para.u() * horizontal + para.v() * vertical);
ray::vec_type color = lerp(r); //得到插值颜色(rgb)
int ir = int(255.99*color.r());
int ig = int(255.99*color.g());
int ib = int(255.99*color.b());
file << ir << " " << ig << " " << ib << stds endl;
}
file.close();
}
else
stds cerr << "load file failed!" << stds endl;
stds cout << "complished" << stds endl;
} int main()
{
build_3_1();
}
下面是效果图(y分量作为插值公式系数)

当然你也可以用x分量作为插值公式系数 t

感谢您的阅读,生活愉快~
【Ray Tracing in One Weekend 超详解】 光线追踪1-2的更多相关文章
- 【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 ...
随机推荐
- Go 语言编程规范
1. gofmt 命令 大部分的格式问题可以通过 gofmt 来解决,gofmt 自动格式化代码,保证所有的 go 代码与官方推荐的格式保持一致,所有格式有关问题,都以gofmt的结果为准.所以,建议 ...
- BFC的个人理解
BFC是Block Formatting Context (块级格式化上下文)的缩写,是一个独立的渲染区域,这个东西的存在是为了隔绝一些内部子元素对外部元素的影响. 例如: 我们用overflow:h ...
- 安装Python和Anaconda
安装Python和Anaconda 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.安装anaconda anaconda包括了Python的集成开发环境. 1.打开下载的网站 ...
- javaweb购物车实现的几种方式
之前没有接触过购物车的东东,也不知道购物车应该怎么做,所以在查询了很多资料,总结一下购物车的功能实现. 查询的资料,找到三种方法: 1.用cookie实现购物车: 2.用session实现购物车: 3 ...
- SQL记录-PLSQL-DBMS输出
PL/SQL DBMS输出 DBMS_OUTPUT是一个内置的软件包,能够显示输出显示调试信息,并从PL/ SQL块,子程序,包和触发器发送消息.我们已经使用这个包在我们所有的教程中. 让我们来看 ...
- Java面试题系列(一)描述一下JVM加载class文件的原理机制
JVM系列第4讲:从源代码到机器码,发生了什么? https://www.cnblogs.com/chanshuyi/p/jvm_serial_04_from_source_code_to_machi ...
- Docker学习笔记一 概念、安装、镜像加速
本文地址:https://www.cnblogs.com/veinyin/p/10406378.html Docker 是一个容器,可以想象成一个轻便的虚拟机,但不虚拟硬件和操作系统. 优点:启动快 ...
- deeplearning.ai学习LSTM
一.LSTM架构与公式 这里的a<t>表示的就是原始输出,y<t>表示的就是经过softmax的输出,c<t>相当于状态.u(update)代表是输入门,f代表遗忘 ...
- 安装informatic过程中的错误
1.Check if the DISPLAY variable is set export DISPLAY=192.168.3.201:0.0 在注销用户并切换到oracle或者infa 用户,就可以 ...
- mac安装sentry
最近需要一个日志监视系统所以选择了sentry. 安装docker https://download.docker.com/mac/stable/Docker.dmg 登录 安装完了打开 会提示登录输 ...