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相关推荐

  1. 【软件开发底层知识修炼】二十七 C/C++中的指针与数组是不同的

    上几篇文章学习了ABI-应用程序二进制接口:[软件开发底层知识修炼]二十六 ABI-应用程序二进制接口 学习总结文章目录 本篇文章就指针与数组的联系与区别来学习学习 文章目录 1 疑问 2 指针与数组 ...

  2. java中的 =运算符_(二十七)、java中的运算符

    一.概述 java的运算符,分为四类: 算数运算符.关系运算符.逻辑运算符.位运算符 算术运算符(9):+   -   *   /   %   ++   -- 关系运算符(6):==   !=   & ...

  3. 【C语言进阶深度学习记录】二十七 C语言中字符串的相等比较

    文章目录 1 字符串的相等比较 1.1 代码分析 1 字符串的相等比较 如果有字符串s1 = "Hello"; s2 = "Hello" ; 在我们看来s1与s ...

  4. tensorflow精进之路(二十七)——人脸识别(中)(MTCNN人脸检查和人脸对齐+FaceNet模型)

    1.概述 上一讲,我们讲了人脸识别的基本原理,这一讲,我们用tensorflow来实现它. 2.下载LFW人脸数据集 2.1.LFW数据集简介 LFW人脸数据集主要用来研究非受限情况下的人脸识别问题, ...

  5. 《Ray Tracing in One Weekend》——Chapter 10: Positionable camera

    总结<Ray Tracing in One Weekend>全文 第一部分:学习总结 问题二十七:ray traing中的positionable camera 第二部分:原文截图 总结& ...

  6. 强化学习系列文章(二十七):VPG+Beta分布在CartPoleContinuous环境中的应用

    强化学习系列文章(二十七):VPG+Beta分布在CartPoleContinuous环境中的应用 在第七篇笔记(https://blog.csdn.net/hhy_csdn/article/deta ...

  7. 问题二十八:ray tracing中的散焦模糊(defocus blur)

    "散焦模糊"在摄影上又称"景深". 在现实的相机中,我们需要做"散焦模糊"的原因是:我们需要一个更大的孔来收集光线增加图片的亮度(而不是&q ...

  8. 2021年大数据Hadoop(二十七):YARN运行流程

    全网最详细的Hadoop文章系列,强烈建议收藏加关注! 后面更新文章都会列出历史文章目录,帮助大家回顾知识重点. 目录 本系列历史文章 前言 Yarn运行流程 本系列历史文章 2021年大数据Hado ...

  9. 【Visual C++】游戏开发笔记二十七 Direct3D 11入门级知识介绍

    游戏开发笔记二十七 Direct3D 11入门级知识介绍 作者:毛星云    邮箱: happylifemxy@163.com    期待着与志同道合的朋友们相互交流 上一节里我们介绍了在迈入Dire ...

最新文章

  1. Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) C. String Reconstruction 并查集
  2. POJ 3278 Catch That Cow
  3. 从volatile解读ConcurrentHashMap(jdk1.6.0)无锁读
  4. 内插以及在数字上变频中的应用
  5. mysql 1005 错误
  6. Java自带的线程池Executors.newFixedThreadPool
  7. python 内部函数传参_python中函数传参详解
  8. 【深度学习】深度学习模型训练全流程!
  9. php数组去空函数怎么写,分享php数组去除空值函数
  10. 修正CS2.0中的日历头显示错误
  11. 截获android屏幕服务,如何捕获android设备屏幕内容?
  12. 解决struts2标签在HTML中错位的问题
  13. Python 06 编码
  14. 两边双虚线是什么意思_【宠物百科】哈士奇双血统是什么意思?
  15. 硬件知识学习整理:(上拉,下拉),(三极管),(OC,OD,推挽输出),(NMOS与PMOS),(MOSFET驱动电路),(IR2110S)
  16. ubuntu 16.04安装网易云音乐,没声音?
  17. Python爬虫之网易云歌单音频爬取(解决urlretrieve爬取文件不能播放问题)
  18. java cloassLoader大仙儿
  19. 【二代示波器教程】第3章 示波器设计—功能划分和准备工作
  20. UC 浏览器曝中间人攻击漏洞,官方:已修复,国内版不受影响

热门文章

  1. 为什么别人一周搞定Linux,而你却做不到
  2. 《Cassandra权威指南》第二版书评及访谈
  3. mongodb维护常用命令
  4. 小博老师精选Java十大CMS ——建站神器
  5. spring : springmvc常用注解标签详解(转)
  6. 用oledb导出数据到excel
  7. Linux-lamp
  8. linux 停止正在执行的shell 程序
  9. codeblocks设置背景主题
  10. C# 通过 AppDomain 应用程序域实现程序集动态卸载或加载