问题二十七:ray traing中的positionable camera
27.1 引入张角theta和宽高比值aspect
回忆一下,“问题十二”中有介绍这么一张图。
当时是这么说的:已知Z=-1平面上四点的坐标,我们可以求出下面三个值。
vec3 lower_left_corner(-2.0, -1.0, -1.0);
vec3 horizontal(4.0, 0.0, 0.0);
vec3 vertical(0.0, 2.0, 0.0);
然后,光线和平面的交点坐标可以表示为向量:lower_left_corner + u*horizontal + v*vertical。这个即为光线的方向向量。
现在引入一个张角theta,和画面宽高比值aspect(这个是已知的)来表示上面三个值。
设整个画面的高为height,半高为half_height,宽为width,半宽为half_width。
引入张角theta,half_height = tan(theta/2)
另外,half_width = aspect * half_height
所以,
vec3 lower_left_corner(-half_width, -half_height,-1.0);
vec3 horizontal(2*half_width, 0.0, 0.0);
vec3 vertical(0.0, 2*half_height, 0.0);
(上面“-1.0”表示图像是画在Z=-1平面)
在运算时,theta一般用的是弧度,而我们在给函数设置参数时使用角度更为方便。所以,引入角度vfov=theta*180/M_PI(即,theta = vfov * M_PI/180)。ofov有个专业的名称:fieldof view
27.2 相机/眼睛/(光线起点)不在原点
先看看,在原点时,我们是怎么表示的。
坐标系的标准正交基e1 = (1, 0, 0), e2 = (0, 1, 0), e3 = (0, 0, 1)。
空间中所有向量(x,y,z)都可以表示为:x e1+ye2+ze3
图像是画在- e3平面(即z = -1)。
lower_left_corner= origin - half_width*e1 - half_height*e2 - e3
horizontal = 2*half_width*e1
vertical = 2*half_height*e2
(这里的origin是原点(0,0,0))
对于任意观测点,我们称:
放相机的位置为lookfrom
我们看的点(画面中心点)为lookat
相机的倾斜方向为view up (简称vup,一般设置为(0,1,0))
有了这三个东东,我们现在就要找出相机在任意点的标准正交基(也就是相机要建立自己的坐标系,然后在自己的坐标系看之前坐标系的物体)。
w = unit_vector(lookfrom - lookat)(w相当于z)
u = unit_vector(cross(vup, w))(u相当于x)
v = cross(w, u)(v相当于y)
w为什么相当于z?这个是由放相机的位置(lookfrom)和目标点(lookat)确定的。
u为什么相当于x?因为相机倾斜方向vup和y比较接近,所以vup和w叉乘之后就是x。
v为什么相当于y?z、x都确定了,还有的选么?另外,w和u的叉乘相当于z、x的叉乘,结果也是y哈。
原坐标系中(x,y,z)对应的标准正交基是e1 , e2 , e3
所以,
w对应e3
u对应e1
v对应e2
之前:
lower_left_corner= origin - half_width*e1 - half_height*e2 - e3
horizontal = 2*half_width*e1
vertical = 2*half_height*e2
所以,现在:
lower_left_corner= origin - half_width*u - half_height*v - w
horizontal = 2*half_width*u
vertical = 2*half_height*v
(注意:对新坐标系来说,所有图像都是画在-w平面上)
由上,我们在此引入了三个参数:lookfrom,lookat, vup
加上上一节中引入的两个参数:vfov,aspect
所以,现在camera类包含了五个参数。
----------------------------------------------camera.h------------------------------------------
camera.h
#ifndef CAMERA_H
#define CAMERA_H#include "ray.h"class camera
{public:camera(vec3 lookfrom, vec3 lookat, vec3 vup, float vfov, float aspect) { // vfov is top to bottom in degreesvec3 u, v, w;float theta = vfov*M_PI/180;float half_height = tan(theta/2);float half_width = aspect * half_height;origin = lookfrom;w = unit_vector(lookfrom - lookat);u = unit_vector(cross(vup, w));v = cross(w, u);lower_left_corner = origin - half_width*u - half_height*v -w;horizontal = 2*half_width*u;vertical = 2*half_height*v;}ray get_ray(float s, float t) {return ray(origin, lower_left_corner + s*horizontal + t*vertical - origin);}vec3 lower_left_corner;vec3 horizontal;vec3 vertical;vec3 origin;};#endif // CAMERA_H
----------------------------------------------main.cpp------------------------------------------
main.cpp
hitable *list[5];
list[0] = new sphere(vec3(0,0,-1), 0.5, new lambertian(vec3(0.1, 0.2,0.5)));
list[1] = new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8,0.8, 0.0)));
list[2] = new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2),0.0));
list[3] = new sphere(vec3(-1,0,-1), 0.5, new dielectric(1.5));
list[4] = new sphere(vec3(-1,0,-1), -0.45, new dielectric(1.5));
hitable *world = new hitable_list(list,5);
camera cam(vec3(-2,2,1), vec3(0,0,-1),vec3(0,1,0), 90, float(nx)/float(ny));
如“问题二十五”中介绍,如上球在原点看是这样的:
改动的相机位置之后是这样的:(vfov = 90)
vfov = 40时是这样的:
vfov = 20时是这样的:
如果去掉该图中的这个球list[3] = new sphere(vec3(-1,0,-1), 0.5, new dielectric(1.5));
结果是这样的:
问题二十七:ray traing中的positionable camera相关推荐
- 【软件开发底层知识修炼】二十七 C/C++中的指针与数组是不同的
上几篇文章学习了ABI-应用程序二进制接口:[软件开发底层知识修炼]二十六 ABI-应用程序二进制接口 学习总结文章目录 本篇文章就指针与数组的联系与区别来学习学习 文章目录 1 疑问 2 指针与数组 ...
- java中的 =运算符_(二十七)、java中的运算符
一.概述 java的运算符,分为四类: 算数运算符.关系运算符.逻辑运算符.位运算符 算术运算符(9):+ - * / % ++ -- 关系运算符(6):== != & ...
- 【C语言进阶深度学习记录】二十七 C语言中字符串的相等比较
文章目录 1 字符串的相等比较 1.1 代码分析 1 字符串的相等比较 如果有字符串s1 = "Hello"; s2 = "Hello" ; 在我们看来s1与s ...
- tensorflow精进之路(二十七)——人脸识别(中)(MTCNN人脸检查和人脸对齐+FaceNet模型)
1.概述 上一讲,我们讲了人脸识别的基本原理,这一讲,我们用tensorflow来实现它. 2.下载LFW人脸数据集 2.1.LFW数据集简介 LFW人脸数据集主要用来研究非受限情况下的人脸识别问题, ...
- 《Ray Tracing in One Weekend》——Chapter 10: Positionable camera
总结<Ray Tracing in One Weekend>全文 第一部分:学习总结 问题二十七:ray traing中的positionable camera 第二部分:原文截图 总结& ...
- 强化学习系列文章(二十七):VPG+Beta分布在CartPoleContinuous环境中的应用
强化学习系列文章(二十七):VPG+Beta分布在CartPoleContinuous环境中的应用 在第七篇笔记(https://blog.csdn.net/hhy_csdn/article/deta ...
- 问题二十八:ray tracing中的散焦模糊(defocus blur)
"散焦模糊"在摄影上又称"景深". 在现实的相机中,我们需要做"散焦模糊"的原因是:我们需要一个更大的孔来收集光线增加图片的亮度(而不是&q ...
- 2021年大数据Hadoop(二十七):YARN运行流程
全网最详细的Hadoop文章系列,强烈建议收藏加关注! 后面更新文章都会列出历史文章目录,帮助大家回顾知识重点. 目录 本系列历史文章 前言 Yarn运行流程 本系列历史文章 2021年大数据Hado ...
- 【Visual C++】游戏开发笔记二十七 Direct3D 11入门级知识介绍
游戏开发笔记二十七 Direct3D 11入门级知识介绍 作者:毛星云 邮箱: happylifemxy@163.com 期待着与志同道合的朋友们相互交流 上一节里我们介绍了在迈入Dire ...
最新文章
- Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) C. String Reconstruction 并查集
- POJ 3278 Catch That Cow
- 从volatile解读ConcurrentHashMap(jdk1.6.0)无锁读
- 内插以及在数字上变频中的应用
- mysql 1005 错误
- Java自带的线程池Executors.newFixedThreadPool
- python 内部函数传参_python中函数传参详解
- 【深度学习】深度学习模型训练全流程!
- php数组去空函数怎么写,分享php数组去除空值函数
- 修正CS2.0中的日历头显示错误
- 截获android屏幕服务,如何捕获android设备屏幕内容?
- 解决struts2标签在HTML中错位的问题
- Python 06 编码
- 两边双虚线是什么意思_【宠物百科】哈士奇双血统是什么意思?
- 硬件知识学习整理:(上拉,下拉),(三极管),(OC,OD,推挽输出),(NMOS与PMOS),(MOSFET驱动电路),(IR2110S)
- ubuntu 16.04安装网易云音乐,没声音?
- Python爬虫之网易云歌单音频爬取(解决urlretrieve爬取文件不能播放问题)
- java cloassLoader大仙儿
- 【二代示波器教程】第3章 示波器设计—功能划分和准备工作
- UC 浏览器曝中间人攻击漏洞,官方:已修复,国内版不受影响