今天,咱們來學習如何設計自定義位置的相機函數
ready學習
咱們只須要了解咱們以前的座標體系,或者說是相機位置測試
先看效果spa
Chapter10:Positionable camera設計
這一章咱們直接用概念貫穿整章3d
1.fov: field of viewcode
它是一個角度blog
它分爲兩種:垂直方向岔開的角度(vfov)和水平方向岔開的角度(hfov)ci
vfov即相機在垂直方向上從屏幕頂端掃描到底部所岔開的視角角度get
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(0.,0.,0.)) { rtvar theta = vfov * π / 180; rtvar half_height = tan(theta / 2); rtvar half_width = aspect * half_height; _start = rtvec(-half_width, -half_height, -1.0); _horizontal = rtvec(2 * half_width, 0., 0.); _vertical = rtvec(0., 2 * half_height, 0.); } 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)看
它應該是一張俯瞰圖
主函數:
如圖:
左邊的金屬球只反射光藍色份量,右邊的漫反射球只反射光的紅色份量
至於藍色的金屬球下部是黑色的,只能解釋爲下部的反射光中藍色成分比較少
因此,過了這一節,咱們的鏡頭就能夠遠近上下左右調整了,屏幕也隨時跟着相機動,爲相機影像作投影
是否是很是激動
前面那張效果圖是以下設置的,球的性質改了一下,且把相機拉近了些(感受書上的距離太遠了)
感謝您的閱讀,生活愉快~