Games101 光栅化笔记, 作业二

2024-04-19 14:48
文章标签 笔记 作业 games101 光栅

本文主要是介绍Games101 光栅化笔记, 作业二,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

光栅化笔记

1、屏幕、像素、屏幕空间:
(1)屏幕:
1、像素的二维数组
2、分辨率:数组的规模
3、典型的光栅成像设备
(2)像素的抽象理解:
1、内部颜色不会变化的小方块
2、RGB三者的颜色混合
(3)对光栅化的理解:对像素进行着色

(4)屏幕空间(在闫老师课上的规定):
1、屏幕的左下角是原点
2、x和y坐标都取整数,下图中蓝色像素坐标为(2,1)
3、像素的索引范围是(0,0)-> (width-1,height-1)
4、(x,y)为像素坐标,则像素中心坐标为(x+0.5,y+0.5)
5、屏幕覆盖范围从(0,0) -> (width,height)
6、视口变换:
投影变换后的(-1,1)正方体向(0,width)×(0,height)屏幕区域的变换,忽略Z方向的改变
在这里插入图片描述
2、将三角形打散成像素——采样
(1)为什么是三角形?
三角形是最基础的多边形;任何多边形多可以拆成三角形;三点一定在同一平面内;三角形的内外定义清晰;对三角形的三个点定义属性,内部的任一点属性都可计算渐变(三角形内部插值)
(2)判断像素和三角形的位置关系
对三角形采样就是判断像素中心是否位于三角形内,如果中心点在三角形外,则一定位于三角形三条边的同一侧,反之不成立。
方向判断用叉乘
P1Q×P1P2 < 0,说明P1Q位于P1P2左侧,同理可判断Q位于P0P1左侧,以及P2P0的左侧。
在这里插入图片描述
边缘条件的判断(比如像素中心位于边上) : 要不不作处理,要么特殊处理,在闫老师的课上不作处理。
(3)采样的加速方法:
1、boundingBox(包围盒):通过三角形的三点坐标计算得出,不用遍历整个屏幕!
在这里插入图片描述
2、每一行只考虑最左和最右,多余一个元素都不计算
在这里插入图片描述
(4)抗锯齿:
发生锯齿的原因:采样率对于信号来讲不够高,产生信号走样

3、走样与反走样
从信号角度理解采样:采样就是重复原始信号的频谱
从信号角度理解走样:
走样的原因即采样率对于信号来讲不够高(信号变化速度快),导致图像的频谱出现交叉现象,结果就是导致锯齿。
在这里插入图片描述

(1)反走样的技术——增加采样率
属于物理手段。
如增加分辨率,像素和像素之间间隔小,采样率更高,频谱间隔大

(2)反走样的技术——滤波
如模糊滤波:先模糊后采样(顺序不能颠倒!),本质是降低信号的频率(减少高频);
在这里插入图片描述
步骤
1、卷积,可看成是和周围的信号取平均 2、采样
在这里插入图片描述

(3)反走样的技术——超采样(Supersampling, MSAA)
将一个像素内分成更多的小部分,再分别判断是否位于三角形内,再卷积采样。
本质是对模糊处理的提升。
代价:提高计算量。

(4)FXAA与TAA
FXAA:快速近似抗锯齿,属于图像的后期处理,找到边界并替换
TAA:复用上一帧的结果抗锯齿

(5)DLSS
当小图拉大时会发生因采样率不够而细节缺失的现象,DLSS使用深度学习的方法”猜“出图像。

4、可见性(遮挡)问题——深度缓存(Z-buffering)
(1)画家算法:
即所有物体,计算深度(O( n l o g n nlogn nlogn)),按照深度顺序,从远到近依次渲染。
但深度的定义是个问题,而且有些物体之间不好明确深度关系,如下图:
在这里插入图片描述
因此在图形学中不能使用画家算法。
(2)深度缓存(Z-buffer):
1、思想:画家算法是对每个物体深度进行排序,而z-buffer则是对每个像素的深度进行排序,将排序结果存储在深度缓存(depth buffer)中,根据深度缓存对进行光栅化。
在Games101课程中,规定越远z越大,越近z越小(与之前规定的z意义不同)。
2、如何计算得到像素深度?
在这里插入图片描述
特点:与扫描三角形的顺序无关(假设不会有两个三角形在同一个像素拥有相同的深度,实际也类似,因为浮点数难以判等)。另外在MSAA中,一个像素被分成多个采样点,则是分别对每个采样点进行判断。

作业二

作业2要求实现三角形光栅化的流程:
(1)计算boundingBox
(2)遍历boundingBox包围的点,并判断是否在三角形内
(3)如果点在三角形内,得到点的深度(插值方法已给出),与深度缓存中的相比较,如果小于,则更新深度缓存,并在屏幕上显示该点

代码:
1、计算boundingBox:

int x_l = std::floor(std::min(v[0][0], std::min(v[1][0], v[2][0])));
int x_r = std::ceil(std::max(v[0][0], std::max(v[1][0], v[2][0])));
int y_b = std::floor(std::min(v[0][1], std::min(v[1][1], v[2][1])));
int y_t = std::ceil(std::max(v[0][1], std::max(v[1][1], v[2][1])));

2、判断点是否位于三角形内:

static bool insideTriangle(int x, int y, const Vector3f* _v)
{   //如果一个点P在三角形ABC内部,即AB*AP,BC*AP,CA*AP,叉乘符号均相同。Vector2f point(x, y);Vector2f AB = _v[1].head(2) - _v[0].head(2);Vector2f BC = _v[2].head(2) - _v[1].head(2);Vector2f CA = _v[0].head(2) - _v[2].head(2);Vector2f AP = point - _v[0].head(2);Vector2f BP = point - _v[1].head(2);Vector2f CP = point - _v[2].head(2);return    AB[0] * AP[1] - AB[1] * AP[0] > 0&& BC[0] * BP[1] - BC[1] * BP[0] > 0&& CA[0] * CP[1] - CA[1] * CP[0] > 0;}

3、遍历boundingBox,如果点位于三角形内:

 //(2)遍历bounding boxfor(int x = x_l ; x <= x_r ; x++)for(int y = y_b ; y <= y_t ; y++) {if(insideTriangle(x + 0.5, y + 0.5, t.v)) { //判断像素中心是否位于三角形内//获取该点的深度,插值计算方法已封装好auto[alpha, beta, gamma] = computeBarycentric2D((float)x + 0.5f, (float)y + 0.5f, t.v);float w_reciprocal = 1.0/(alpha / v[0].w() + beta / v[1].w() + gamma / v[2].w());float z_interpolated = alpha * v[0].z() / v[0].w() + beta * v[1].z() / v[1].w() + gamma * v[2].z() / v[2].w();z_interpolated *= w_reciprocal;//将深度与深度缓存中的相比较,如果小于则更新深度缓存并在屏幕上画出if (depth_buf[get_index(x, y)] > z_interpolated) {Vector3f color = t.getColor();Vector3f point(3);point << (float)x, (float)y, z_interpolated;depth_buf[get_index(x, y)] = z_interpolated;set_pixel(point, color);}}}

这篇关于Games101 光栅化笔记, 作业二的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/917850

相关文章

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

查看提交历史 —— Git 学习笔记 11

查看提交历史 查看提交历史 不带任何选项的git log-p选项--stat 选项--pretty=oneline选项--pretty=format选项git log常用选项列表参考资料 在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的 工具是 git log 命令。 接下来的例子会用一个用于演示的 simplegit

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

忽略某些文件 —— Git 学习笔记 05

忽略某些文件 忽略某些文件 通过.gitignore文件其他规则源如何选择规则源参考资料 对于某些文件,我们不希望把它们纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常它们都是些自动生成的文件,比如日志文件、编译过程中创建的临时文件等。 通过.gitignore文件 假设我们要忽略 lib.a 文件,那我们可以在 lib.a 所在目录下创建一个名为 .gi

取得 Git 仓库 —— Git 学习笔记 04

取得 Git 仓库 —— Git 学习笔记 04 我认为, Git 的学习分为两大块:一是工作区、索引、本地版本库之间的交互;二是本地版本库和远程版本库之间的交互。第一块是基础,第二块是难点。 下面,我们就围绕着第一部分内容来学习,先不考虑远程仓库,只考虑本地仓库。 怎样取得项目的 Git 仓库? 有两种取得 Git 项目仓库的方法。第一种是在本地创建一个新的仓库,第二种是把其他地方的某个