【Ray Tracing in One Weekend 超詳解】 光線追蹤1-8 自定義相機設計

 

今天,咱們來學習如何設計自定義位置的相機函數

 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)看

它應該是一張俯瞰圖

 

 主函數:

 

 如圖:

 

 

左邊的金屬球只反射光藍色份量,右邊的漫反射球只反射光的紅色份量

至於藍色的金屬球下部是黑色的,只能解釋爲下部的反射光中藍色成分比較少

 

因此,過了這一節,咱們的鏡頭就能夠遠近上下左右調整了,屏幕也隨時跟着相機動,爲相機影像作投影

是否是很是激動

 

前面那張效果圖是以下設置的,球的性質改了一下,且把相機拉近了些(感受書上的距離太遠了)

 

感謝您的閱讀,生活愉快~

相關文章
相關標籤/搜索