Computer Graphics From Scratch - Chapter 9

news2024/11/19 21:20:20

系列文章目录

简介:Computer Graphics From Scratch-《从零开始的计算机图形学》简介
第一章: Computer Graphics From Scratch - Chapter 1 介绍性概念
第二章:Computer Graphics From Scratch - Chapter 2 基本光线追踪
第三章:Computer Graphics From Scratch - Chapter 3 光照
第四章:Computer Graphics From Scratch - Chapter 4 阴影和反射
第五章:Computer Graphics From Scratch - Chapter 5 扩展光线追踪
第六章:Computer Graphics From Scratch - Chapter 6 线条
第七章:Computer Graphics From Scratch - Chapter 7 实心三角形
第八章:Computer Graphics From Scratch - Chapter 8 阴影三角形


Chapter 9

  • 系列文章目录
  • Perspective Projection - 透视投影
  • 一、Basic Assumptions - 基本假设
  • 二、Finding P' - 寻找点P'
  • 三、The Projection Equation - 投影方程
  • 四、Properties of the Projection Equation - 投影方程的性质
  • 五、Projecting Our First 3D Object - 投影我们的第一个 3D 对象
  • 六、Summary - 概括


Perspective Projection - 透视投影

So far, we have learned to draw 2D triangles on the canvas, given the 2D coordinates of their vertices. However, the goal of this book is to render 3D scenes. So in this chapter, we’ll take a break from 2D triangles and focus on how to turn 3D scene coordinates into 2D canvas
coordinates. We’ll then use this to draw 3D triangles on the 2D canvas.

到目前为止,我们已经学会了在画布上绘制 2D 三角形,给定其顶点的 2D 坐标。
但是,本书的目标是渲染3D场景。因此,在本章中,我们将从 2D 三角形中休息一下,重点介绍如何将 3D 场景坐标转换为 2D 画布坐标。然后,我们将使用它在 2D 画布上绘制 3D 三角形。


一、Basic Assumptions - 基本假设

就像我们在第 2 章开头所做的那样,我们将从定义相机时代开始。 我们将使用与之前相同的约定:
相机位于 O = ( 0 , 0 , 0 ) O = (0, 0, 0) O=(0,0,0),看向 Z + → \overset{\rightarrow}{Z_+} Z+的方向,它的“向上”向量是 Y + → \overset{\rightarrow}{Y_+} Y+
我们还将定义一个大小为 V w V_w Vw V h V_h Vh 的矩形视口 (viewport) ,其边缘平行于 X → \overset{\rightarrow}{X} X Y → \overset{\rightarrow}{Y} Y,距离相机 d d d
目标是在画布上绘制任何东西相机通过视口看到。 如果您需要复习这些概念,请参阅第 2 章。


考虑相机前方某处的 P P P点。我们感兴趣的是找到 P ′ P^′ P,即摄像机在视口上看到 P P P 的点,如图 9-1 所示。
在这里插入图片描述

图 9-1:简单的透视投影设置。相机看到投影平面上的P到P’。

这与我们对光线追踪所做的相反。
我们的光线追踪器从画布上的一个点开始,并确定它可以通过该点看到什么;
在这里,我们从场景中的某个点开始,并希望确定它在视口上的可见位置。


二、Finding P’ - 寻找点P’

要找到 P ′ P′ P ,让我们从字面上从不同的角度看图 9-1 中所示的设置。
图 9-2 显示了从“右侧”查看的设置图,就好像我们站在 X ⃗ \vec{X} X 轴上一样: Y + ⃗ \vec{Y_+} Y+ 指向上方, Z + ⃗ \vec{Z_+} Z+ 指向右侧, X + ⃗ \vec{X_+} X+ 指向我们。
在这里插入图片描述

图 9-2:从右侧查看的透视投影设置

除了 O O O P P P P ′ P^′ P 之外,这张图还显示了点 A A A B B B,这有助于我们推理它。

我们知道 P z ′ = d P^′_z = d Pz=d,因为我们将 P ′ P^′ P 定义为视口上的一个点,并且我们知道视口嵌入在平面
Z = d Z = d Z=d 中。

我们还可以看到三角形 OP’AOPB 是相似的,因为它们对应的边(P′APB、OP 和 OP′OAOB)是平行的。这意味着它们侧面的比例是相同的;
例如:

∣ P ′ A ∣ ∣ O A ∣ = ∣ P B ∣ ∣ O B ∣ \dfrac{|P'A|}{|OA|} = \dfrac{|PB|}{|OB|} OAPA=OBPB

由此,我们得到
∣ P ′ A ∣ = ∣ P B ∣ ⋅ ∣ O A ∣ ∣ O B ∣ |P'A| = \dfrac{|PB| \cdot |OA|}{|OB|} PA=OBPBOA
该等式中每个段的(有符号)长度是我们知道或我们感兴趣的点的坐标:
∣ P ′ A ∣ = P y ′ |P^′ A|= P^′_y PA=Py ∣ P B ∣ = P y |PB|= P_y PB=Py ∣ O A ∣ = P z ′ = d |OA|= P^′_z = d OA=Pz=d, 和 ∣ O B ∣ = P z |OB|= P_z OB=Pz
如果我们在等式中替换这些,我们得到

P y ′ = P y ⋅ d P z P'_y = \dfrac{P_y \cdot d}{P_z} Py=PzPyd


我们可以绘制一个类似的图,这次从上方查看设置:

Z + ⃗ \vec{Z_+} Z+ 点向上, X + ⃗ \vec{X_+} X+ 指向右侧, Y + ⃗ \vec{Y_+} Y+ 指向我们(图9-3)。
在这里插入图片描述

图 9-3:透视的俯视图投影设置

以相同的方式再次使用类似的三角形,我们可以推断出:
P x ′ = P x ⋅ d P z P'_x = \dfrac{P_x \cdot d}{P_z} Px=PzPxd
我们现在拥有 P ′ P' P 的所有三个坐标。


三、The Projection Equation - 投影方程

让我们把所有这些放在一起。
给定场景中的点 P 以及标准的摄像机和视口设置,我们可以计算 P 在视口上的投影,我们称之为 P′,如下所示:

P x ′ = P x ⋅ d P z P'_x = \dfrac{P_x \cdot d}{P_z} Px=PzPxd
P y ′ = P y ⋅ d P z P'_y = \dfrac{P_y \cdot d}{P_z} Py=PzPyd
P z ′ = d P'_z = d Pz=d

P′ 位于视口上,但它仍然是 3D 空间中的一个点。我们如何在画布中获得相应的点?

我们可以立即删除 P z ′ P'_z Pz,因为每个投影点都在视口平面上。
接下来,我们需要将 P x ′ P'_x Px P y ′ P'_y Py 转换为画布坐标 C x C_x Cx C y C_y Cy
P ′ P' P 仍然是场景中的一个点,因此其坐标以场景单位表示。

我们可以将它们除以视口的宽度和高度。这些也以场景单位表示,因此我们获得临时无单位的值。

最后,我们将它们乘以画布的宽度和高度,以像素表示:
C x = P x ′ ⋅ C w V w C_x = \dfrac{P'_x \cdot C_w}{V_w} Cx=VwPxCw

C y = P y ′ ⋅ C h V h C_y = \dfrac{P'_y \cdot C_h}{V_h} Cy=VhPyCh

这种视口到画布的变换与我们在本书光线追踪部分使用的画布到视口变换完全相反。有了这个,我们终于可以从场景中的一个点变成屏幕上的像素了!


四、Properties of the Projection Equation - 投影方程的性质

在我们继续之前,投影有一些有趣的属性值得讨论的方程式。

上面的方程式应该与我们看待现实世界事物的日常经验兼容。
例如,物体离得越远,它看起来越小;事实上,如果我们增加 P z P_z Pz,我们会变小 P x ′ P'_x Px P y ′ P'_y Py的值。

然而,当我们过多地降低 P z P_z Pz的值时,事情就不再那么直观了;

对于 P z P_z Pz 的负值,即当一个物体在相机后面时,物体仍然被投影,但颠倒了!

当然,当 P z = 0 P_z = 0 Pz=0 时,我们将除以零,宇宙就会内爆。

我们需要找到一种方法来避免这些不愉快的情况; 现在,我们假设每个点都在镜头前,并在后面的章节中处理。


透视投影的另一个基本属性是它保持点对齐

如果三个点在空间中对齐,它们的投影将在视口上对齐。

换句话说,直线总是被投影为直线。 这听起来太明显而不值得一提,但请注意,例如,两条线之间的角度并没有保持不变;

在现实生活中,我们看到平行线在地平线上“汇合”,例如在高速公路上行驶时。


直线总是被投影为直线这一事实对我们来说非常方便:到目前为止我们谈论的是投影一个点,但是如何投影一条线段,甚至是一个三角形呢?

由于这个性质,两点之间的线段投影就是两点投影之间的线段;

三角形的投影是由其顶点的投影形成的三角形。


五、Projecting Our First 3D Object - 投影我们的第一个 3D 对象

这意味着我们可以继续绘制我们的第一个 3D 对象:立方体。

我们定义它的 8 个顶点的坐标,并在构成立方体边的 12 对顶点的投影之间绘制线段,如示例 9-1 所示。

ViewportToCanvas(x, y) {
return (x * Cw/Vw, y * Ch/Vh);
}
ProjectVertex(v) {
return ViewportToCanvas(v.x * d / v.z, v.y * d / v.z)
}
// The four "front" vertices
vAf = [-1, 1, 1]
vBf = [ 1, 1, 1]
vCf = [ 1, -1, 1]
vDf = [-1, -1, 1]
// The four "back" vertices
vAb = [-1, 1, 2]
vBb = [ 1, 1, 2]
vCb = [ 1, -1, 2]
vDb = [-1, -1, 2]
// The front face
DrawLine(ProjectVertex(vAf), ProjectVertex(vBf), BLUE);
DrawLine(ProjectVertex(vBf), ProjectVertex(vCf), BLUE);
DrawLine(ProjectVertex(vCf), ProjectVertex(vDf), BLUE);
DrawLine(ProjectVertex(vDf), ProjectVertex(vAf), BLUE);
// The back face
DrawLine(ProjectVertex(vAb), ProjectVertex(vBb), RED);
DrawLine(ProjectVertex(vBb), ProjectVertex(vCb), RED);
DrawLine(ProjectVertex(vCb), ProjectVertex(vDb), RED);
DrawLine(ProjectVertex(vDb), ProjectVertex(vAb), RED);
// The front-to-back edges
DrawLine(ProjectVertex(vAf), ProjectVertex(vAb), GREEN);
DrawLine(ProjectVertex(vBf), ProjectVertex(vBb), GREEN);
DrawLine(ProjectVertex(vCf), ProjectVertex(vCb), GREEN);
DrawLine(ProjectVertex(vDf), ProjectVertex(vDb), GREEN);

Listing 9-1: Drawing a cube

We get something like Figure 9-4 .

在这里插入图片描述

Figure 9-4: Our first 3D object projected on a 2D canvas: a cube

You can find a live implementation of this algorithm at
https://gabrielgambetta.com/cgfs/perspective-demo.

我们已经成功地从物体的几何3D表示转变为从我们的合成相机看到的2D表示!

不过,我们的方法是非常手工的。它有许多局限性。如果我们想渲染两个立方体呢?我们必须复制大部分代码吗?如果我们想渲染立方体以外的东西,该怎么办?如果我们想让用户从文件中加载三维模型,该怎么办?我们显然需要一种更加数据驱动的方法来表示3D几何。


六、Summary - 概括

在本章中,我们开发了从场景中的3D点到画布上的2D点的数学方法。由于透视投影的特性,我们可以立即将其扩展到投影线段,然后扩展到三维对象。

但我们还有两个重要问题没有解决。首先,示例9-1将透视投影逻辑与立方体的几何体混合在一起;这种方法显然不会扩大规模。其次,由于透视投影方程的限制,它无法处理相机后面的物体。我们将在接下来的两章中讨论这些问题。


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IEEE 最佳论文提名 | TraND:用步态算法优化身份识别

来源:投稿 作者:小灰灰 编辑:学姐 论文标题:TraND: Transferable Neighborhood Discovery for Unsupervised Cross-domain Gait Recognition 论文链接: https://arxiv.org/pdf/2102.04621v1.pdf 步态识别开始应用在公共场域身份…

centos mysql安装配置远程访问

包含以下三个部分:mysql安装,mysql密码重置、mysql配置远程访问。 一 centos安装mysql 1、wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm 2、yum -y install mysql57-community-release-el7-10.noarch.rpm 3、yum…

to be delete

一、grafana版本升级 1.1 还是先跟着官网简单走一波 建议经常升级Grafana,以获取最新的修补程序和增强功能。 为了实现这一点,Grafana升级向后兼容,并且升级过程简单快捷。升级通常是安全的(在许多次要版本和一个主要版本之间&a…

Python习题进阶

1.十六进制数字的大小 描述 计算的世界,除了二进制与十进制,使用最多的就是十六进制了,现在使用input读入一个十六进制的数字,输出它的十进制数字是多少? 输入描述: input读入一个十六进制数字&#xf…

微信支付服务商接入指引(企业)

目录 一、官方指引二、申请流程1.进入服务商平台2.填写资料3.账户验证&资料审核 三、登录 一、官方指引 https://kf.qq.com/faq/161220iqeAfA1612202yeURB.html 二、申请流程 1.进入服务商平台 https://pay.weixin.qq.com/static/partner_guide/service_provider.shtml…

【JVM快速入门篇】

本笔记内容为狂神说JVM快速入门篇部分 目录 一、JVM的位置 二、JVM体系结构 三、类加载器(ClassLoader) 四、双亲委派机制 双亲委派机制的作用 五、沙箱安全机制 六、Native ​编辑Native Method Stack 本机方法栈 Native Ilnterface本地接口…

低代码靠谱吗?实操一遍就知道了

一、前言 最近一段时间,“低代码”概念特别流行,有些人特别推崇它,也有些人对此不屑一顾。 推崇它的人认为,它有很多优点,比如说能够降低开发周期,提高系统开发效率,降低开发成本,学…

使用HBuilder将h5网站打包成app 自行打包

1、点击manifest.json,基础配置,APP名字,是否全面屏 2、然后点击图标配置,选好后点自动生成所有图标并替换 点击模块配置,选VideoPlayer和X5内核 然后顶部菜单选发行,选择原生App-云打包 选公测证书然后…

WPF教程-XAML介绍

XAML介绍 1.定义 为构建应用程序用户界面而创建的一种新的“可扩展应用程序标记语言”,提供一种便于扩展和定位的语法来定义和程序业务逻辑分离的用户界面。 XAML 是一种 XML(Extensible Markup Language)的扩展,XAML 是 WPF 中…

云计算——云计算与虚拟化的关系

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​ 目录 前言 一.虚拟化 1.什么是虚拟化 2.虚拟化技术作用 二.云计算与虚拟化的关系 三.虚…

一文让非技术宅读懂为什么AI更“喜欢”GPU而不是CPU?

一、引言 随着人工智能(AI)技术的快速发展,深度学习等算法在图像识别、自然语言处理、数据挖掘等方面表现出了强大的能力。而这些算法的底层计算,往往对硬件有着极高的要求。为了满足这些需求,越来越多的研究和工程实…

关于不同型号电脑谷歌浏览器下载指定版本的方法(超详细教程)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1、根据链接打开地址2、页面说明3、下载过程(1)选中指定版本点击它(这里以52.0.27.37.1为例)(2&…

美国访学博后答疑|尚未出国DS-2019表格过期了怎么办?

美国执J1签证者尚未出国,但DS-2019表格过期了怎么办?本篇知识人网老师就以下三种情况,统一做答疑建议。 美国访问学者和博士后的签证类型多是J1签证,需要由美国接收方将签字后的DS2019表邮寄给国内,申请者本人在表格正…

多项安全新功能为云上安全保驾护航,就在亚马逊云科技re:Inforce全球大会

亚马逊云科技re:Inforce 2023全球大会于当地时间2023年6月13日在美国加州安纳海姆拉开帷幕。在大会上,亚马逊云科技宣布推出十多项安全新服务及功能,下面就来一览本次大会的风采。 “Security is our top priority.” “安全是我们的首要优先级”&#…

Socket 传情:使用 Python 发送 GET 请求

文章目录 参考描述HTTPHTTP 报文HTTP 请求报文请求行请求头空行请求体 HTTP 响应报文状态行响应头空行响应体 HTTP 请求方法HTTP 与 TCP 协议HTTP 协议TCP 协议 httpbin.org socket 模块socket.socket()Socket().connect()Socket().send() 与 Socket().sendall()Socket().recv(…

AI实战营第二期 第十节 《MMagic 代码课》——笔记11

AI实战营第二期 第十节 《MMagic 代码课》 MMagic (Multimodal Advanced, Generative, and Intelligent Creation) 是一个供专业人工智能研究人员和机器学习工程师去处理、编辑和生成图像与视频的开源 AIGC 工具箱。 MMagic 允许研究人员和工程师使用最先进的预训练模型&…

wms add window 流程

二、WMS 窗口添加流程 /frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,boolean andResume, boolean checkConfig) throws RemoteException {.....…

ESP-C2模组 AT示例程序

ESP32C2 AT固件使用 ESP32 C2模组,如图1-1所示 图1-1 ESP32 C2模组 ESP32 C2开发板,如图1-2所示 图1-2 ESP32 C2开发 方案亮点 1、完整的 WiFi 子系统,符合 IEEE 802.11b/g/n 协议,具有 Station 模式、SoftAP 模式、SoftAP Stat…

2023电商运营课程培训课程干货

​电商运营是当今社会最为火热的词汇之一,在各个领域有着广泛的运用。各种途径的线上销售使得产品的销售以及品牌的推广变得更加容易,因此越来越多的人选择从事电商运营。而电商运营的成功离不开专业的培训,为此许多机构推出了电商运营课程培…

python数据结构详解

Python是一种高级编程语言,它具有简单易学的语法和强大的数据结构。在Python中,数据结构是指一组数据和与之相关的操作的集合。Python提供了许多数据结构,包括列表、元组、字典、集合和字符串。本文将深入介绍Python中的数据结构,…