光栅化(Rasterization)

news2025/1/15 19:59:19

MVP复习

1)Model transformation(placing objects) = 找好一个场景,让人物摆好姿势

2)View transformation(placing camera) = 放置好照相机

利用camera和物体的相对运动关系,始终让camera从任一位置变换到原点看向-z方向且向上为y,其余物体也跟着camera做相同的变换,从而保证model transformation应用到每一个model上,并且view transformation也应用到了每一个model上。

3)Projection transformation = 按下快门,将三维物体表现在二维平面上

在view transformation之后我们知道场景中的所有物体都是由一个标准位置的camera看过去的,接着将所看到的东西从3D投影成2D的一张照片。又分为正交投影(忽略深度信息)和透视投影(拥有近打远小的效果)。

经过mvp变换矩阵之后的所有东西都会在一个 [ − 1 , 1 ] 3 [-1,1]^3 [1,1]3的立方体里,那么下一步该干什么呢?答案是“光栅化”!

但在讲光栅化之前先看如果根据已知的Near、Far、Fov、Aspect来定义frustum:

在这里插入图片描述

aspect是宽高比,说的是Near和Far。

而Fov则是从camera,点A处,往上下两边的中点各连一条线,而两条线的夹角叫垂直可视角度。同理也可以求出水平可视角度,往左右两边的中点各连一条线,而两条线的夹角叫水平可视角度。

Near和Far是两个面的位置。

在这里插入图片描述

有了这些已知条件就可以计算推导出Near和Far的面积有多大,以及知道一个垂直可视角度就可以推导出水平可视角度。

接下来我们来了解如何将 [ − 1 , 1 ] 3 [-1,1]^3 [11]3的立方体画在屏幕上

光栅化概念导入

对于图形学来说,我们抽象的将屏幕定义为一个二维的数组,数组中的每一个元素是一个像素(an array of pixels)。

(tips:例如1920 * 1080分辨率,就是说长为1920个像素点,宽为1080个像素点,总像素为1920 * 1080个像素,也叫做1080P。)

屏幕是一个典型的光栅成像设备。Raster的由来是德语中屏幕的意思,而光栅化(Rasterize)就是把东西画在屏幕上的意思。所以把东西画在屏幕上的过程就是光栅化的过程

像素:

像素名字的由来是picture element,我们将其缩写为pixel

在图形学中我们将像素看为:

  • 是一个一个的小的方块.
  • 每个方块内的颜色是完全一致的,像素就是最小的单位了,像素内部不会再发生变化。
  • 我们用256个等级0-255来表示灰度(如等级0表示是黑的,等级255表示是白的),一个像素内的颜色可以用rgb(red,green,blue)三个值来定义,用红绿蓝的各种组合来表示每一种红色蓝色绿色的密度,例如红色是(255,0,0),白色是(255,255,255)。
  • 一个像素内颜色不会发生任何差异。

屏幕空间:

屏幕空间就是以屏幕左下角为原点建立一个二维坐标系,如下图:

在这里插入图片描述

  • 用(x,y)表示像素的位置。(蓝色像素表示为(2,1)坐标来表示,从0开始数。)
  • 如果一个屏幕分辨率为width * height,那么我们定义像素下标从(0,0)到(width - 1,height - 1),且(x,y)像素的中心在(x + 0.5, y + 0.5),如蓝色像素的中心为(2.5, 1.5)。
  • 屏幕范围从(0,0)到(width,height)

现在我们需要把这个中心在坐标原点 [ − 1 , 1 ] 3 [-1,1]^3 [1,1]3的立方体显示在长为height、宽为width的屏幕中,先不考虑Z值,如下图所示:

在这里插入图片描述

第二步的具体操作是进行一次视口变换(viewport),准确地说是通过缩放平移变换将原本的 [ − 1 , 1 ] 2 [-1,1]^2 [1,1]2拉伸到屏幕空间中并将中心移动到屏幕空间中心,视口变换矩阵(viewport transform matrix)如下:
M v i e w p o r t = [ w i d t h 2 0 0 w i d t h 2 0 h e i g h t 2 0 h e i g h t 2 0 0 1 0 0 0 0 1 ] M_{viewport}= \left[ \begin{matrix} width \over 2 & 0 & 0 & width \over2 \\ 0 & height \over2 & 0 & height \over2 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right] Mviewport= 2width00002height0000102width2height01
至此我们得到了一张映射在屏幕空间的2D场景图,接下来我们要将场景中的多边形其离散成一系列的像素画在屏幕空间上。

Drawing to Raster Displays

光栅化的过程实际上就是将多边形拆分成一系列的像素,从而将3D空间中的多边形或多边形的顶点变换到屏幕空间上去。

一般将图像拆分成许多不同的三角形 进行显示,下图是由三角形表示的二维空间的不同的图形。

在这里插入图片描述

我们可以看到三角形的表达能力很强,不论是在3D还是2D中,之所以选择三角形是因为:

  • 三角形是最最基础的多边形。
  • 任何多边形均可以拆解成多个三角形。

三角形具有不错的性质:

Ⅰ. 三角形的三个点连接在一起,其三点一定在一个平面上。

Ⅱ. 三角形的内外部定义的很清楚,可以通过向量的叉积判断点是否在三角形内部。

A Simple Approach: Sampling(采样)

在这里插入图片描述

我们知道一个像素内部是不会再发生颜色变化的,那三角形三条边上只包含了像素一部分的这些区域该如何设置颜色呢?是有颜色还是无颜色呢?

因此我们需要判断一个像素和三角形之间的位置关系,更确切的来说是判断像素的中心点与三角形之间的位置关系

而这个关系的判断我们可以通过采样实现。

采样:采样就是把一个函数给离散化的过程,可以理解为给你一个连续的函数,在不同地方问此处的函数值是多少,这就是采样.

例如f(x) = sinx,让你求x=1,x=3,x=5或者x=-1时候的对应的f(x)的值是多少,如:

在这里插入图片描述

采样就是把一个函数离散化的过程。

我们这里的采样是通过利用像素中心对屏幕空间进行采样,也就是算出定义在屏幕空间上的某一函数在不同像素中心的值是多少。

采样是图形学的核心理念,可以采样的:时间(1D)、面积(2D)、方向(2D)、体积(3D)等。

光栅化作为2D采样

在这里插入图片描述

给你一个三角形,我们需要在像素中心来判断其是否在三角形内。

在这里插入图片描述

我们可以定义一个inside函数,来判断像素是否在三角形内:

在这里插入图片描述

for (int x = 0; x < xmax; ++x)
    for (int y = 0; y < ymax; ++y)
        image[x][y] = inside(tri,  x + 0.5,  y + 0.5);
        x,y不必为整数,是实数。

屏幕空间是[0,width] x [0,height]这么一个区域,我们利用像素中心来进行采样就是指算出需要某一个定义在屏幕空间内的函数在不同的像素中心的值是多少

比如我们在这里采样的就是在屏幕空间中定义的inside函数在不同像素中心的值,在不同像素中心采样到的结果是1则在三角形内,是0则在三角形外,通过这个值我们来判断此像素是否在三角形内.

这个函数具体是如何判断像素点在不在三角形内部则是通过向量叉乘运算得到的。如果正巧点在三角形边线上,那可以自己定义一个规则。

遍历像素

接下来就可以遍历屏幕像素将三角形显示在屏幕中了

有两种较为高效的扫描遍历策略Bounding BoxIncremental Triangle Traversal

(Bounding Box) 检测像素的步骤:

  1. 首先通过三角形三个顶点的 x,y 的坐标从最小值到最大值选出包围盒(Bounding Box)。即蓝色包围部分,去掉第一列白色部分。

  2. 严格来说这个又叫做轴向包围盒=AABB包围盒(Axis-aligned bounding box)

  3. 在蓝色区域内进行采样,使用inside函数确定像素中心点的值。

在这里插入图片描述

(Incremental Triangle Traversal)增量三角形遍历:

对三角形所覆盖的区域每一行找覆盖的最左和最右,相当于在每一行确定一个包围盒。

这种方法适用于实际上覆盖了很少的像素但AABB包围盒范围却很大的情况,也就是一个窄长三角形经历了旋转的情况下。

在这里插入图片描述

最终我们采样信号显示为:

在这里插入图片描述

我们找到了那些像素是在三角形内部的,接着我们对其进行颜色填充。

锯齿

在像素内进行颜色填充之后会变为下图,我们称这种情况为锯齿(Jaggies)现象。出现的原因是 因为像素本身具有大小,采样率不高,从而信号走样(Aliasing)。

在这里插入图片描述

与我们想要的效果不一样:

在这里插入图片描述

锯齿一直是图形学在不断改进的问题,下节课将介绍如何解决“锯齿”问题,引入抗锯齿和反走样的概念。

光栅化的过程其实就是我们将3D空间的多边形离散成屏幕空间一系列的点(像素的中心点),并通过采样某一定义在屏幕空间的函数的结果判断那些像素需要着色从而将多边形显示在屏幕空间上。

Anti-aliasing

反走样的主要思想是,在采样之前进行模糊处理(Antialiasing idea:bluring before sampling).

如果不先进行模糊处理而是直接对三角形采样,由于我们是通过像素中心点来采样,得到的结果这个像素点要么在三角形内像素点纯红,要么在三角形外像素点纯白,最终会导致锯齿:

在这里插入图片描述

如果我们先做一遍模糊处理在进行采样:

在这里插入图片描述

我们会发现采样点增加了,并且在边缘处有一些颜色比较淡的点,也就是采样到了模糊三角形的边界。

三角形的原锯齿边缘的像素取了一个介于红色和白色之间的像素值,离边界近就接近红色,离边界远就接近白色,再进行染色时,边缘的像素点就会染色为中间值,边缘就能够获得一些更加平滑的效果,起到抗锯齿的作用。

这也就是对原始的函数或者信号进行了一个模糊或者滤波的处理,然后再去做采样,从而解决了锯齿的问题。

先采样再模糊并不能实现抗锯齿的效果,其仍然得到的是一个走样的结果,只不过在走样之后又进行了模糊操作,称其为Blurred Aliasing,并不是Anti-Aliasing。

硬件支持:提高显示器分辨率。如果用一个640*480的显示器,光栅化一个三角形,就能够明显发现锯齿很严重,但是如果使用1920 * 1080的显示器就能够明显改善这种情况,采样的密集了,走样现象也就会减少。但是这种情况需要依赖于高分辨率的显示器,若是显示器分辨率不能改变时,这种方法就不行了。

MSAA(Antialiasing By Supersampling)

MSAA是一个对反走样的近似,之前采样的最小单位是像素的中心点,在MSAA中,我们将以划分的每个像素再进行划分,将原有的一个像素分为更多个小像素.如下图,我们将原来的一个像素的区域又重新划分为了4*4 = 16 个像素的新区域.

在这里插入图片描述

而重新划分的每一个小像素也都有一个像素中心,然后可以对这个小像素进行采样,判断这些小像素在不在三角形内,然后将最后的结果平均起来,就能够求的三角形对一个像素的区域的近似的覆盖。比如:

在这里插入图片描述

可以看到一个三角形覆盖了若干个很大的原像素.

现在假设说我们将原有的一个大像素分为四个小像素,也就是在像素内部多加一些采样点,这就导致了时域上我们采样的间隔变小,频域上的频谱搬移空间变大,从而进行了反走样.

在这里插入图片描述

然后每个点都可以判断是否在三角形内,如果四个点都在三角形内就是100%覆盖,也就是100%的红色,如果只有三个点在三角形内,则三角形对这个像素就是75%覆盖,其颜色也就是75%的红色+25%的白色。于是就可以得出每个像素的覆盖结果:

在这里插入图片描述

MSAA通过更多的样本,来近似的进行反走样的第一步,模糊这个过程。模糊完了之后就相当于每一个像素内部都已经知道了三角形的覆盖率,求了平均之后是什么,就会得到上图的结果。

到了这一步,就相当于模糊做完了,就相当于用卷积核对图像进行了一次卷积得到了模糊的效果。

然后再采样,这时采样就会十分简单,因为我们规定像素是最小的单位格子,每个格子的颜色都是平均的(像素内的颜色都是一样的),采样完也就会得到上图的结果。

注意!!!

  • MSAA所进行的是一个模糊的操作,而采样这一步隐含在了MSAA的过程中.
  • MSAA并不是一个提升分辨率直接解决的走样问题. (我们增加采样点只是为了近似一个合理的三角形在像素点上的覆盖率,并没有真的提升分辨率.)
  • MSAA的缺陷就是,我们增加了采样点也就是增加了计算量,将一个像素划分为多个区域,就要对每个区域进行多次计算,最后就提高了计算的成本。

Z-buffering

Painter’s Algorithm:画家算法,由远及近画画,近处画面覆盖远处画面。无法处理复杂的深度判断,例如三个三角形互相重叠。如果事先把深度排序的话时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn).

Z-buffer:额外开辟一块屏幕大小的空间存放像素深度。渲染之前先于存放的值进行比较,如果深度更近则进行绘制,并更新值。空间换时间,时间复杂度 O ( n ) O(n) O(n)

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

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

相关文章

LeetCode(力扣)669. 修剪二叉搜索树Python

LeetCode669. 修剪二叉搜索树 题目链接代码 题目链接 https://leetcode.cn/problems/trim-a-binary-search-tree/ 代码 递归 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # …

VS + QT 封装带UI界面的DLL

一、创建编译DLL的项目 1.新建Qt Class Liabrary 2.新建项目&#xff0c;选择Qt Widgets Class 3.新建C类&#xff0c;可以在此类里面写算法函数用于调用。 4.下面是添加完Qt窗体类和C类之后的项目截图 5.修改头文件并编译 将uidemo_global.h中的ifdef内容复制到dialog.h上…

心脏出血漏洞复现(CVE-2014-0160)

CVE-2014-0160&#xff1a;Heartbleed 介绍&#xff1a; 认识&#xff1a;首先简单介绍一下这个漏洞&#xff0c;该漏洞是一个出现在加密程序库OpenSSL的安全漏洞&#xff0c;这个程序呢&#xff0c;是在传输层协议TLS协议之上&#xff0c;这个协议呢被称为心跳协议&#xff0…

Linux操作系统中的信号剖析,

1、前言 信号是一种信息载体&#xff0c;在现实中&#xff0c;信号就是表示消息的物理量&#xff0c;比如说红绿灯&#xff0c;古时候狼烟等等&#xff0c;就拿红绿灯来说&#xff0c;为什人和车辆都是看到绿灯才会通行&#xff0c;红灯亮了就要停下来&#xff0c;因为这是现实…

鉴源论坛 · 观模丨基于应用程序编程接口(API)的自动化测试(上)

作者 | 黄杉 华东师范大学软件工程学院博士 苏亭 华东师范大学软件工程学院教授 版块 | 鉴源论坛 观模 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 01 应用程序编程接口&#xff08;API&#xff09; 应用程序编程接口&#xff0c;英文全称为Applica…

UI自动化之关键字驱动

关键字驱动框架&#xff1a;将每一条测试用例分成四个不同的部分 测试步骤&#xff08;Test Step&#xff09;&#xff1a;一个测试步骤的描述或者是测试对象的一个操作说明测试步骤中的对象&#xff08;Test Object&#xff09;&#xff1a;指页面的对象或者元素对象执行的动…

浪潮信息Owen ZHU:大模型百花齐放,算力效率决定速度

与狭义的人工智能相比&#xff0c;通用人工智能通过跨领域、跨学科、跨任务和跨模态的大模型&#xff0c;能够满足更广泛的场景需求、实现更高程度的逻辑理解能力与使用工具能力。2023年&#xff0c;随着 LLM 大规模语言模型技术的不断突破&#xff0c;大模型为探索更高阶的通用…

打磨 8 个月、功能全面升级,Milvus 2.3.0 文字发布会现在开始!

Milvus 社区的各位伙伴&#xff1a; 大家晚上好&#xff01;欢迎来到 Milvus 2.3.0 文字发布会&#xff01; 作为整个团队的匠心之作&#xff0c;Milvus 2.3.0 历经 8 个月的设计与打磨&#xff0c;无论在新功能、应用场景还是可靠度方面都有不小的提升。 具体来看&#xff1a;…

电脑莫名其妙重启 为设备 ROOT\DISPLAY\0000 加载驱动程序 \Driver\WUDFRd 失败

卸载向日葵即可解决&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;下面是报错日志&#xff0c;估计是远程连接导致的问题

Flask项目请求图片资源返回403错误

问题 解决 在图片url前缀前加 "https://images.weserv.nl/?url" 参考 如何解决访问外部图片返回 403 Forbidden 错误 - 知乎 vue中请求接口会自动带上本地ip_vite打包后请求地址为什么带本地地址_夜月晓晓的博客-CSDN博客

3D点云处理:基于PCA计算点云位姿 平面位姿(附源码)

文章目录 1. 基本内容2. PCA求解步骤(非公式推导)3. 代码实现4. 参考文章目录:3D视觉个人学习目录微信:dhlddxB站: Non-Stop_1. 基本内容 基于PCA计算点云位姿通常是指在三维空间中使用PCA(主成分分析)来估计点云数据的姿态或定位,即确定点云数据在三维空间中的位置(平移…

2022年12月 C/C++(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;漫漫回国路 2020年5月&#xff0c;国际航班机票难求。一位在美国华盛顿的中国留学生&#xff0c;因为一些原因必须在本周内回到北京。现在已知各个机场之间的航班情况&#xff0c;求问他回不回得来&#xff08;不考虑转机次数和机票价格&#xff09;。 时间限…

idea 链接mysql连不上

打开文件 C:\Program Files\JetBrains\IntelliJ IDEA 2023.2.1\jbr\conf\security\java.security修改内容 搜索&#xff1a;jdk.tls.disabledAlgorithms 修改 链接地址 在链接后面添加 ?useSSLfalse jdbc:mysql://127.0.0.1:3306/db_admin3?useSSLfalse

java+jsp+servlet+mysql蛋糕商城

项目介绍&#xff1a; 本系统为基于jspservletmysql的蛋糕商城&#xff0c;包含管理员和用户角色&#xff0c;用户功能如下&#xff1a; 用户&#xff1a;注册、登录系统&#xff1b;查看商品分类&#xff1b;查看热销、新品商品&#xff1b;查看商品详情&#xff1b;搜索商品…

XSS漏洞及复现

一、什么是XSS 跨站脚本( Cross-site Scripting )攻击&#xff0c;攻击者通过网站输入框输入payload(脚本代码 )&#xff0c;当用户访问网页时&#xff0c;恶意payload自动加载并执行&#xff0c;以达到攻击者目的( 窃取cookie、恶意传播、钓鱼欺骗等)为了避免与HTML语言中的C…

(数学) 剑指 Offer 62. 圆圈中最后剩下的数字 ——【Leetcode每日一题】

❓ 剑指 Offer 62. 圆圈中最后剩下的数字 难度&#xff1a;简单 0, 1, ,n-1 这 n 个数字排成一个圆圈&#xff0c;从数字 0 开始&#xff0c;每次从这个圆圈里删除第 m 个数字&#xff08;删除后从下一个数字开始计数&#xff09;。求出这个圆圈里剩下的最后一个数字。 例如…

最新文献怎么找|学术最新前沿文献哪里找

查找下载最新文献最好、最快、最省事的方法就是去收录该文献的官方数据库中下载。举例说明&#xff1a; 有位同学求助下载一篇2023年新文献&#xff0c;只有DOI号10.1038/s41586-023-06281-4&#xff0c;遇到这种情况可以在DOI号前加上http://doi.org/输入地址栏查询该文献的篇…

数据结构:排序解析

文章目录 前言一、常见排序算法的实现1.插入排序1.直接插入排序2.希尔排序 2.交换排序1.冒泡排序2.快速排序1.hoare版2.挖坑版3.前后指针版4.改进版5.非递归版 3.选择排序1.直接选择排序2.堆排序 4.归并排序1.归并排序递归实现2.归并排序非递归实现 5.计数排序 二、排序算法复杂…

DDR2 IP核调试记录1

一、IP核生成不成功可能原因 1、打开 Quartus II 软件时&#xff0c;请右键选择以管理员方式运行&#xff0c;切记&#xff0c;否则可能导致 IP 生成不成功。 2、创建工程时不要将工程创建在和 Quartus II 安装目录相同的盘符下&#xff0c;否则可能导致生产 IP 失败。 3、如果…

Revit SDK:AutoJoin 自动合并体量

前言 Revit 有一套完整的几何造型能力&#xff0c;每一个体量都是一个GenericForm&#xff0c;这些体量可以通过拉伸、扫掠等创建。这个例子介绍如何将他们合并成一个体量。 内容 合并体量的关键接口&#xff1a; // Autodesk.Revit.DB.Document public GeomCombination Com…