今天,我们来学习如何设计自定义位置的相机

ready

我们只需要了解我们之前的坐标体系,或者说是相机位置

先看效果

  Chapter10:Positionable camera

这一章我们直接用概念贯穿整章

1.fov: field of view

它是一个角度

它分为两种:垂直方向岔开的角度(vfov)和水平方向岔开的角度(hfov)

vfov即相机在垂直方向上从屏幕顶端扫描到底部所岔开的视角角度

hfov即相机在水平方向上从屏幕左端扫描到右端所岔开的视角角度

2.aspect:屏幕宽高比

我们之前是通过直接定义屏幕的坐标位置来确定屏幕,现在,我们可以通过相机参数来确定屏幕

目前,我们暂时还用ready中的坐标,相机在原点,屏幕中心在(0,0,-1)

我们习惯采用vfov,这里我们假设一直vfov和aspect

眼睛离屏幕中心的距离为dis(也就是1)

根据 tan(vfov/2) = (屏幕高/2)/dis

得到 屏幕高 = 2 * dis * tan(vfov/2)

则,屏幕上边界为 y_up = dis * tan(vfov/2)

  屏幕下边界为 y_bottom = - y_up 

屏幕宽 = 屏幕高 * aspect

则,屏幕左边界为 x_left = - 屏幕宽/2

  屏幕右边界为 x_right = - x_left

所以,我们目前的相机类如下:

/// 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(rtvar vfov, rtvar aspect)
:_eye(rtvec(.,.,.))
{
rtvar theta = vfov * π / ;
rtvar half_height = tan(theta / );
rtvar half_width = aspect * half_height;
_start = rtvec(-half_width, -half_height, -1.0);
_horizontal = rtvec( * half_width, ., .);
_vertical = rtvec(., * half_height, .);
} inline const ray get_ray(const rtvar u,const rtvar v)const
{ return ray{ _eye, _start + u*_horizontal + v*_vertical }; } inline const ray get_ray(const lvgm::vec2<rtvar>& para)const
{ return ray{_eye, _start + para.u()*_horizontal + para.v()*_vertical}; } 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; } private:
rtvec _eye; rtvec _start; //left-bottom rtvec _horizontal; rtvec _vertical; }; } #endif

同时,我们如下设置main的相关数据,先来测试一下

Lambertian(rtvec(0,0,1))过滤red和green,完全保留blue

得到如下图:

没问题吧,屏幕宽为4,高为2,两边少的部分是被视锥体切掉了

从原点往左右边界连线,左三角面和右三角面内的部分才可见

3.lookfrom:相机所在位置

4.lookat:相机视线指向的位置点

相机在lookfrom位置看向lookat点

5.相机平面

相机平面是过lookfrom垂直于视线(from->at)的一个平面

类似于坐标系,确定平面当然也需要正交基向量,而相机三维正交基一般采用uvw坐标系

一个个描述

在阐述uvw之前先确定一个正向上的向量,因为相机坐标系算是一个局部性质的,当我们把它放在世界坐标系中,就需要用一个始终指向世界坐标系正上方的基向量vup(view up)

我们现在来确定三维正交相机坐标系

我们先来确定w,w是一个正交于相机平面的基向量

它的定义为 w = lookfrom - lookat 

即:与视线反向的一个基向量

有了w,我们便可以定义u了,u向量代表相机平面的水平向量

u一定平行于世界坐标系的x轴

vup平行于世界坐标系的y轴

所以u⊥vup

而w⊥相机平面,所以w⊥u

所以  u = vup × w   该体系为右手系

最后定义v,v就是相机平面的垂直方向

即, v = w × u 

所以,我们可以定义一个完整的camera类啦

构造函数改动如下:

我们试着,站在(-2,2,1)位置,往屏幕中心(0,0,-1)看

它应该是一张俯瞰图

主函数:

如图:

左边的金属球只反射光蓝色分量,右边的漫反射球只反射光的红色分量

至于蓝色的金属球下部是黑色的,只能解释为下部的反射光中蓝色成分比较少

所以,过了这一节,我们的镜头就可以远近上下左右调整了,屏幕也随时跟着相机动,为相机影像做投影

是不是非常激动

前面那张效果图是如下设置的,球的性质改了一下,且把相机拉近了些(感觉书上的距离太远了)

感谢您的阅读,生活愉快~

【Ray Tracing in One Weekend 超详解】 光线追踪1-8 自定义相机设计的更多相关文章

  1. 【Ray Tracing The Next Week 超详解】 光线追踪2-9

    我们来整理一下项目的代码 目录 ----include --hit --texture --material ----RTdef.hpp ----ray.hpp ----camera.hpp ---- ...

  2. 【Ray Tracing The Next Week 超详解】 光线追踪2-6 Cornell box

    Chapter 6:Rectangles and Lights 今天,我们来学习长方形区域光照  先看效果 light 首先我们需要设计一个发光的材质 /// light.hpp // ------- ...

  3. 【Ray Tracing in One Weekend 超详解】 光线追踪1-4

    我们上一篇写了Chapter5 的第一个部分表面法线,那么我们来学剩下的部分,以及Chapter6. Chapter5:Surface normals and multiple objects. 我们 ...

  4. 【Ray Tracing The Next Week 超详解】 光线追踪2-7 任意长方体 && 场景案例

    上一篇比较简单,很久才发是因为做了一些好玩的场景,后来发现这一章是专门写场景例子的,所以就安排到了这一篇 Preface 这一篇要介绍的内容有: 1. 自己做的光照例子 2. Cornell box画 ...

  5. 【Ray Tracing The Next Week 超详解】 光线追踪2-8 Volume

     Preface 今天有两个东东,一个是体积烟雾,一个是封面图 下一篇我们总结项目代码 Chapter 8:Volumes 我们需要为我们的光线追踪器添加新的物体——烟.雾,也称为participat ...

  6. 【Ray Tracing The Next Week 超详解】 光线追踪2-5

    Chapter 5:Image Texture Mapping 先看效果: 我们之前的纹理是利用的是撞击点p处的位置信息,比如大理石纹理 而我们今天的图片映射纹理采用2D(u,v)纹理坐标来进行. 在 ...

  7. 【Ray Tracing The Next Week 超详解】 光线追踪2-4 Perlin noise

     Preface 为了得到更好的纹理,很多人采用各种形式的柏林噪声(该命名来自于发明人 Ken Perlin) 柏林噪声是一种比较模糊的白噪声的东西:(引用书中一张图) 柏林噪声是用来生成一些看似杂乱 ...

  8. 【Ray Tracing The Next Week 超详解】 光线追踪2-3

     Preface 终于到了激动人心的纹理章节了 然鹅,看了下,并不激动 因为我们之前就接触过 当初有一个 attenuation 吗? 对了,这就是我们的rgb分量过滤器,我们画出的红色.蓝色.绿色等 ...

  9. 【Ray Tracing The Next Week 超详解】 光线追踪2-2

    Chapter 2:Bounding Volume Hierarchies 今天我们来讲层次包围盒,乍一看比较难,篇幅也多,但是咱们一步一步来,相信大家应该都能听懂 BVH 和 Perlin text ...

随机推荐

  1. codeblocks编译器

    发现网络有些编译器没有MinGW,特此留一文件: https://pan.baidu.com/s/1pLltzvH 有时下载codeblocks后编译不了,还要修改MinGW的位置,找到MinGW文件 ...

  2. 个推应用统计产品(个数)Android集成实践

    前段时间,我们公司的产品又双叒叕给我们提了新需求,要求我们把APP相关的数据统计分析一下,这些指标包括但不限于应用每日的新增.活跃.留存率等等,最好每天都能提供数据报表.这种事情真是想想就麻烦,大家最 ...

  3. Docker:搭建私有仓库(Registry 2.4)

    一.背景 首先,Docker Hub是一个很好的用于管理公共镜像的地方,我们可以在上面找到想要的镜像(Docker Hub的下载量已经达到数亿次):而且我们也可以把自己的镜像推送上去.但是,有的时候, ...

  4. bzoj千题计划221:bzoj1500: [NOI2005]维修数列(fhq treap)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 1.覆盖标记用INF表示无覆盖标记,要求可能用0覆盖 2.代表空节点的0号节点和首尾的两个虚拟 ...

  5. IEnumerator和IEnumerable详解

    IEnumerator和IEnumerable 从名字常来看,IEnumerator是枚举器的意思,IEnumerable是可枚举的意思. 了解了两个接口代表的含义后,接着看源码: IEnumerat ...

  6. [转载]TypeScript 入门指南

    之前有听过,但未使用过,而最近在用nodejs,angularjs做一些前端项目,想到了这个来,正是学习TypeScript的时候,看介绍貌似和coffeescript相似,也JavaScript的转 ...

  7. javascript强大的日期函数

    var date = function( a, s ) { var d = s ? new Date( s ) : new Date(), f = d.getTime(); return ( '' + ...

  8. 关于SQL注入,你应该知道的那些事

    戴上你的黑帽,现在我们来学习一些关于SQL注入真正有趣的东西.请记住,你们都好好地用这些将要看到的东西,好吗? SQL注入攻击因如下几点而是一种特别有趣的冒险: 1.因为能自动规范输入的框架出现,写出 ...

  9. 关于Spring mvc注解中的定时任务的配置

    关于spring mvc注解定时任务配置 简单的记载:避免自己忘记,不是很确定我理解的是否正确.有错误地方望请大家指出. 1,定时方法执行配置: (1)在applicationContext.xml中 ...

  10. 第12月第2天 uiscrollview _adjustContentOffsetIfNecessary 圆角

    1. uiscrollview在调用setFrame,setBounds等方法的时候会默认调用稀有api: _adjustContentOffsetIfNecessary 这个方法会改变当前的cont ...