光线追踪11 - Positionable Camera(可定位相机)

相机和介质一样,调试起来很麻烦,所以我总是逐步开发我的相机。首先,我们允许可调节的视野(fov)。这是渲染图像从一边到另一边的视觉角度。由于我们的图像不是正方形的,水平和垂直的视野是不同的。我总是使用垂直视野。通常我会用角度来指定,然后在构造函数内部转换为弧度 — 这只是个人喜好的问题。

12.1 Camera Viewing Geometry
 首先,我们将保持从原点出发并指向z = -1平面的光线。我们可以将其设置为z = -2平面,或任何其他平面,只要我们将h与该距离成比例即可。以下是我们的设置:

Figure 18: Camera viewing geometry (from the side)

This implies  h = tan\frac{\theta }{2} , Our camera now becomes:

class camera {
  public:    double aspect_ratio      = 1.0;  // Ratio of image width over height
int    image_width       = 100;  // Rendered image width in pixel count
int    samples_per_pixel = 10;   // Count of random samples for each pixel
int    max_depth         = 10;   // Maximum number of ray bounces into scene

double vfov = 90;  // Vertical view angle (field of view)

void render(const hittable& world) {
    ...
  private:
   ...
   void initialize() {
      image_height = static_cast<int>(image_width / aspect_ratio);
      image_height = (image_height < 1) ? 1 : image_height;

      center = point3(0, 0, 0);

      // Determine viewport dimensions.
        auto focal_length = 1.0;
        auto theta = degrees_to_radians(vfov);
        auto h = tan(theta/2);
        auto viewport_height = 2 * h * focal_length;
auto viewport_width=viewport_height*(static_cast<double>(image_width)/image_height);

// Calculate the vectors across the horizontal and down the vertical viewport edges.
        auto viewport_u = vec3(viewport_width, 0, 0);
        auto viewport_v = vec3(0, -viewport_height, 0);

        // Calculate the horizontal and vertical delta vectors from pixel to pixel.
       pixel_delta_u = viewport_u / image_width;
        pixel_delta_v = viewport_v / image_height;

        // Calculate the location of the upper left pixel.
        auto viewport_upper_left =
            center - vec3(0, 0, focal_length) - viewport_u/2 - viewport_v/2;        pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v);
    }
    ...
};

Listing 74: [camera.h] Camera with adjustable field-of-view (fov)


我们将使用一个90°的视野来测试这些变化,以两个相互接触的球体构成的简单场景为例。

int main() {
hittable_list world;
auto R = cos(pi/4);
auto material_left  = make_shared<lambertian>(color(0,0,1));
auto material_right = make_shared<lambertian>(color(1,0,0));
world.add(make_shared<sphere>(point3(-R, 0, -1), R, material_left));
world.add(make_shared<sphere>(point3( R, 0, -1), R, material_right));
camera cam;
cam.aspect_ratio      = 16.0 / 9.0;
cam.image_width       = 400;
cam.samples_per_pixel = 100;
cam.max_depth         = 50;
cam.vfov = 90;
cam.render(world);
}

得到渲染结果:

Image 19: A wide-angle view

12.2 Positioning and Orienting the Camera(定位和定向相机)

为了获得任意的viewpoint,让我们首先给出我们关心的点的名称。我们将摄像机放置的位置称为"lookfrom",我们注视的点称为"lookat"。(稍后,如果需要,可以定义一个注视方向而不是注视点。)
我们还需要一种方式来指定摄像机的倾斜角度,也就是绕"lookat-lookfrom"轴的旋转。另一种思考方式是,即使保持"lookfrom"和"lookat"不变,你仍然可以围绕你的鼻子旋转头部。我们需要的是一种为摄像机指定"up"向量的方法。

Figure 19: Camera view direction


        我们可以指定任何一个up向量,只要它不与视线方向平行。将这个up向量投影到与视线方向正交的平面上,得到一个相对于相机的up向量。我使用常见的约定将其命名为“view up”(vup)向量。经过几次叉乘和向量归一化,我们现在有了一个完整的正交基(u、v、w),用于描述相机的方向。u是指向相机右侧的单位向量,v是指向相机上方的单位向量,w是指向视线方向相反的单位向量(由于我们使用右手坐标系),相机中心位于原点。

Figure 20: Camera view up direction


与以前一样,当我们的固定相机面向-Z时,我们的任意视角相机面向-w。请记住,我们可以选择使用世界坐标系的上方向(0,1,0)来指定vup,但不是必须的。这种方法很方便,可以让你的相机在水平方向保持平稳,直到你决定尝试一些疯狂的相机角度为止。

class camera {
  public:
double aspect_ratio      = 1.0;  // Ratio of image width over height
    int    image_width       = 100;  // Rendered image width in pixel count
    int    samples_per_pixel = 10;   // Count of random samples for each pixel
    int    max_depth         = 10;   // Maximum number of ray bounces into scene
    double vfov     = 90;              // Vertical view angle (field of view)
    point3 lookfrom = point3(0,0,-1);  // Point camera is looking from
    point3 lookat   = point3(0,0,0);   // Point camera is looking at
    vec3   vup      = vec3(0,1,0);     // Camera-relative "up" direction
    ...
  private:    int    image_height;   // Rendered image height
    point3 center;         // Camera center
    point3 pixel00_loc;    // Location of pixel 0, 0
    vec3   pixel_delta_u;  // Offset to pixel to the right
    vec3   pixel_delta_v;  // Offset to pixel below
    vec3   u, v, w;        // Camera frame basis vectors

    void initialize() {
       image_height = static_cast<int>(image_width / aspect_ratio);
       image_height = (image_height < 1) ? 1 : image_height;

        center = lookfrom;

        // Determine viewport dimensions.
        auto focal_length = (lookfrom - lookat).length();
        auto theta = degrees_to_radians(vfov);
       auto h = tan(theta/2);
        auto viewport_height = 2 * h * focal_length;
Auto viewport_width = viewport_height * (static_cast<double>(image_width) / image_height);

        // Calculate the u,v,w unit basis vectors for the camera coordinate frame.
        w = unit_vector(lookfrom - lookat);
        u = unit_vector(cross(vup, w));
        v = cross(w, u);

    // Calculate the vectors across the horizontal and down the vertical viewport edges.
        vec3 viewport_u = viewport_width * u; // Vector across viewport horizontal edge
       vec3 viewport_v = viewport_height * -v; // Vector down viewport vertical edge

        // Calculate the horizontal and vertical delta vectors from pixel to pixel.
       pixel_delta_u = viewport_u / image_width;
        pixel_delta_v = viewport_v / image_height;

        // Calculate the location of the upper left pixel.
        auto viewport_upper_left=center-(focal_length*w)-viewport_u/2-viewport_v/2;
        pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v);
}
    ...
  private:
};

Listing 76: [camera.h] Positionable and orientable camera


我们将回到之前的场景,并使用新的视点:

int main() {
hittable_list world;

auto material_ground = make_shared<lambertian>(color(0.8, 0.8, 0.0));
auto material_center = make_shared<lambertian>(color(0.1, 0.2, 0.5));
auto material_left   = make_shared<dielectric>(1.5);
auto material_right  = make_shared<metal>(color(0.8, 0.6, 0.2), 0.0);

    world.add(make_shared<sphere>(point3( 0.0, -100.5, -1.0), 100.0, material_ground));
    world.add(make_shared<sphere>(point3( 0.0,    0.0, -1.0),   0.5, material_center));
    world.add(make_shared<sphere>(point3(-1.0,    0.0, -1.0),   0.5, material_left));
world.add(make_shared<sphere>(point3(-1.0,    0.0, -1.0),  -0.4, material_left));
world.add(make_shared<sphere>(point3( 1.0,    0.0, -1.0),   0.5, material_right));

camera cam;

    cam.aspect_ratio      = 16.0 / 9.0;
    cam.image_width       = 400;
    cam.samples_per_pixel = 100;
    cam.max_depth         = 50;

    cam.vfov     = 90;
    cam.lookfrom = point3(-2,2,1);
    cam.lookat   = point3(0,0,-1);
    cam.vup      = vec3(0,1,0);

    cam.render(world);
}

Listing 77: [main.cc] Scene with alternate viewpoint

得到:

Image 20: A distant view
 

修改  field of view :
    cam.vfov     = 20;
Listing 78: [main.cc] Change field of view

变为:

Image 21: Zooming in

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/436543.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

初次实战SQL注入

目录 1.判断漏洞是否存在 2.判断注入类型&#xff08;数字型/字符型&#xff09; 3.猜列数 4.联合查询判断回显位 6.获取数据库表明 此实验为本人学习内容&#xff0c;从未攻击任何网站&#xff01;&#xff01;&#xff01;请伙伴们同样遵纪守法&#xff01;&#xff01;…

转录组总结

1. 软件安装 2.转录组分析步骤&#xff1a; ① 建立环境 #建立python2.7的环境&#xff0c;大部分的转录组信息都需要在Python2的环境下进行 conda create -n py2env python2.7 source activate py2env ② 获取fastqc报告 #单个报告 fastqc -t 15 /home/yinwen/biosoft/DN…

2024年数据库系统工程师全套资料

2024年5月数据库系统工程师全套视频、历年真题及解析、历年真题视频解析、教材、模拟题、重点笔记等资料 1、2023年5月、2022年5月、2021年5月数据库系统工程师全套基础精讲视频。2024年5月全套精讲视频持续更新中。 2、数据库系统工程师2004-2023年历年真题及解析文档&#x…

如何在Win系统部署Tomcat服务并实现远程访问内网站点

文章目录 前言1.本地Tomcat网页搭建1.1 Tomcat安装1.2 配置环境变量1.3 环境配置1.4 Tomcat运行测试1.5 Cpolar安装和注册 2.本地网页发布2.1.Cpolar云端设置2.2 Cpolar本地设置 3.公网访问测试4.结语 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的人工智能学…

读架构整洁之道的一些感悟

做产品开发时&#xff0c;我们经常跌落在一种无法打破的轮回中。 我们经常说&#xff0c;产品上线最重要&#xff0c;可以未来再重构代码&#xff0c; 但是结果大家都知道&#xff0c;产品上线以后重构工作就再没人提起了。首先&#xff0c;线上跑的好好的&#xff0c;动出问题…

动态规划(算法竞赛、蓝桥杯)--树形DP树的中心

1、B站视频链接&#xff1a;E34 树形DP 树的中心_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; const int N20010; int n,a,b,c,ans2e9; struct edge{int v,w;}; vector<edge> e[N]; int d1[N],d2[N],path[N],up[N];//path记录d1 void dfs1(in…

【Vue】sessionStorage存取数据

一. 需求 1.1 模板 Vab Admin Pro 1.2 组件 ElementUI 1.3 阐述 列表页面搜索【关键词】点击【查询】后&#xff0c;点击【查看】按钮跳转到【详情页】&#xff0c;详情页【返回】【保留原搜索关键词】 原图 搜索查询【关键词】 详情 返回后【保留】【搜索查询关键词…

潜水耳机哪个牌子好?认准这几个游泳耳机品牌就对了!

在科技日益发达的今天&#xff0c;人们对于运动设备的需求也在不断提升。作为一项独特的水上运动&#xff0c;潜水爱好者们对耳机的要求也越来越高。一款优秀的潜水耳机不仅能够提供卓越的防水性能和舒适度&#xff0c;还必须具备出色的音质。那么&#xff0c;在众多品牌中&…

2024宠物行业未来发展趋势:京东宠物健康(宠物营养保健和医疗)市场品类数据分析报告

近段时间&#xff0c;广州某知名宠物医院的医疗事故正在被大众热议&#xff0c;也让越来越多从业者开始关心宠物医疗行业的未来形势。 在2022年下半年&#xff0c;京东平台专门设立了一个一级大类目&#xff1a;宠物健康&#xff08;将其从原本的宠物生活类目中独立出来&#…

【C++】c++入门之递归上 数值类

文章目录 前言一、 递归1.1 基本概念1.2 递归的过程1.3 使用场景 二、例题讲解问题一&#xff1a;1002 - 编程求解123...n问题二&#xff1a;1241 - 角谷猜想问题三&#xff1a;1108 - 正整数N转换成一个二进制数问题四&#xff1a;1088 - 求两个数M和N的最大公约数 三、练习问…

Chrome禁止自动升级

一、关闭计划任务 1、首先我们需要右键点击我的电脑&#xff0c;在打开的选项里选择管理。   2、在打开的对话框中选择任务计划程序。   3、在任务计划程序库中找到两个和chrome自动更新相关的任务计划GoogleUpdateTaskMachineCore与GoogleUpdateTaskMachineUA。     4…

onlyOffice-windows 安装说明(二)

onlyoffice windows 安装 onlyoffice 支持多个平台比如&#xff1a;Windows Server、Linux、Docker 以下内容是对官网安装说明做了简单翻译&#xff0c;仅供参考&#xff0c;原文链接地址参见文末。 社区版允许您在本地服务器上安装ONLYOFFICE文档&#xff0c;并将在线编辑器…

【李沐精读系列】BERT精读

论文&#xff1a;BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 参考&#xff1a;BERT论文逐段精读、李沐精读系列、李宏毅版BERT讲解 一、介绍 BERT(Bidirectional EncoderRepresentation Transformer&#xff0c;双向Transformer编码器…

JAVA 用二分法查找数组中是否存在某个值

二分法查找的概念 二分查找也称折半查找&#xff08;Binary Search&#xff09;&#xff0c;它是一种效率较高的查找方法。首先&#xff0c;将表中间位置记录的关键字与查找关键字比较&#xff0c;如果两者相等&#xff0c;则查找成功&#xff1b;否则利用中间位置记录将表分成…

pinia报错does not provide an export named ‘hasInjectionContext

你们好&#xff0c;我是金金金。 场景 我这里是uniappvue3编写的一个小程序项目&#xff0c;在集成pinia过程当中遇到此问题&#xff0c;报错请求的模块 未提供 导出名hasInjectionContext&#xff08;位于 pinia.mjs:6:10&#xff09; 以下我项目当中vue和pinia的具体依赖版本…

selenium等待机制

selenium等待机制 影响元素加载的外部因素1.计算机的性能2.服务器的性能3.浏览器的性能4.网络因素 强制等待1.强制等待2.页面加载超时机制 隐性等待显性等待1.WebDriverWait类2.WebDriverWait类提供的方法untileuntile_not显性等待的语法格式 3.expected_conditions模块方法exp…

「Mybatis深入三」:高级查询-模糊查询

一、需求 根据username 模糊查询user 表 二、代码演示 1、方式1 数据库环境 CREATE DATABASE mybatis_db; USE mybatis_db; CREATE TABLE user (id INT(11) NOT NULL AUTO_INCREMENT,username VARCHAR(32) NOT NULL COMMENT 用户名称,birthday DATETIME DEFAULT NULL COMMEN…

Java开发从入门到精通(一):Java的基础语法进阶

Java大数据开发和安全开发 &#xff08;一&#xff09;Java注释符1.1 单行注释 //1.2 多行注释 /* */1.3 文档注释 /** */1.4 各种注释区别1.5 注释的特点1.5 注释的快捷键 &#xff08;二&#xff09;Java的字面量&#xff08;三&#xff09;Java的变量3.1 认识变量3.2 为什么…

【宏观经济】全国各地级市及上市公司“信息惠民国家试点”DID(2010-2024)

数据说明&#xff1a;信息惠民国家试点城市是&#xff0c;2014年6月23日&#xff0c;根据国家发改委网站发布的通知&#xff0c;国家发展改革委等12部门决定的&#xff0c;将全国80个城市列为信息惠民国家试点城市。推进信息惠民国家试点城市建设&#xff0c;有利于加快提升公共…

vue+Nodejs+Koa搭建前后端系统(九)-- 上传图片

web2.0的到来使网页世界正式进入了寒武纪&#xff0c;各式各样的多媒体资源屡见不鲜&#xff0c;上传资源变得刻不容缓&#xff01; 前言 本文是在该系列的基础上&#xff0c;针对前后端代码的修改。 准备 HTTP上传图片时Content-Type值常见的有2种&#xff1a;application…