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

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. 螺旋队列和hiho1525逃离迷宫3

    我是真调不出错误了! hiho1525逃离迷宫3 #include <stdio.h> #include <stdlib.h> #include <math.h> ...

  2. JQuery中2个等号与3个等号的区别

    首先,== equality 等同,=== identity 恒等.==, 两边值类型不同的时候,要先进行类型转换,再比较.===,不做类型转换,类型不同的一定不等. 下面分别说明:先说 ===,这个 ...

  3. 使用WebHelper调用Asp.net WebAPI

    1.WebHelper using System; using System.Collections.Generic; using System.Collections.Specialized; us ...

  4. html之div始终停留在屏幕中间部分

    需求: 使得某一个div始终停留在屏幕中间 实现: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...

  5. ReactJS -- 初学入门

    <!DOCTYPE html> <html> <head> <script src="build/react.js"></sc ...

  6. [python]python错误集锦

    ValueError: invalid literal : ''不能将非数字字符串转换为整型 object has no attribute 对象调用一个没有的方法(内建或自定义) TypeError ...

  7. 《区块链100问》第13集:比特币和Q币有哪些不同?

    比特币是一种去中心化的数字资产,没有发行主体.Q币是由腾讯公司发行的电子货币,类似于电子积分,其实不是货币. Q币需要有中心化的发行机构,Q币因为腾讯公司的信用背书,才能被认可和使用.使用范围也局限在 ...

  8. Expression Tree Build

    The structure of Expression Tree is a binary tree to evaluate certain expressions.All leaves of the ...

  9. Identical Binary Tree

    Check if two binary trees are identical. Identical means the two binary trees have the same structur ...

  10. 终极利器!利用appium和mitmproxy登录获取cookies

    环境搭建 参考我之前写的https://www.cnblogs.com/c-x-a/p/9163221.html appium 代码start_appium.py # -*- coding: utf- ...