光栅化 Rasterization
文章目录
- 1 光栅化 Rasterization
- 1.1 视口变换 viewport (正则立方体 to 屏幕)
- 1.2 像素化
- 1.2.1 三角形构成图像
- 1.2.2 三角形离散化
- 1.2.2.1 叉乘判断点是否在三角形内
- 1.2.2.2 三角形像素化使用包围盒
- 1.2.3 效果
- 2 反走样 Antialiasing
- 2.1 提前滤波 Pre-Filter
- 2.2 滤波原理
- 2.2.1 频域与傅里叶变换
- 2.2.2 滤波
- 2.2.3 卷积 Convolution
- 2.2.4 低通滤波盒子
- 2.2.4 采样等于重复频率内容***
- 2.3 低通滤波采样
- 2.3.1 超采样 MSAA Multisample anti-aliasing
- 3 作业 光栅化三角形
- 4 总结
1 光栅化 Rasterization
raster
来自 德语 ,意思是屏幕
,动词化后变rasterize
再名词化Rasterization
,意为光栅化
.- 像素
Pixel
是picture element
,可理解为屏幕最小单位
,为正方形
,颜色为RGB
.
1.1 视口变换 viewport (正则立方体 to 屏幕)
像素指标从(0,0)
到(宽-1,高-1)
,每个像素中心
坐标是(x+0.5,y+.5)
把MVP
变换的正则立方体
(先不管z轴
,只看x
和y
)[-1,1]²
投到屏幕(0×宽,0×高)
,
需要一个视口变换矩阵 viewport
到达让正方形左下角点
在屏幕原点
,右上角点
在屏幕右上角顶点
的效果.
1.2 像素化
1.2.1 三角形构成图像
经过视口变换,图像
已经在屏幕上
了.
现在研究怎么用屏幕表现图像
,也就是屏幕上每个像素值
是多少. 我们认为图像基本单元是三角形
,有了通过像素组成
的单个三角形
,我们可以通过三角形集合
得到各种图像
. (PS. 早期的电视也是用CRT
通过打电子到屏幕
来显示画面)
- 用三角形是因为
- 三角形是
最基础多边形
- 三角形
三点在一平面
- 方便判断
点在三角形内外
- 方便
重心插值
1.2.2 三角形离散化
所以换句话说,就是怎么在屏幕画三角形,即 Rasterizing Triangles into Pixels
.
采样近似
,用inside函数
判断像素点是否在三角形内
- 伪代码
1.2.2.1 叉乘判断点是否在三角形内
1.2.2.2 三角形像素化使用包围盒
只遍历AABB盒子,避免计算量过大
1.2.3 效果
大概像个三角形,但是有锯齿 Jaggies!!!
- 真实例子: 手机屏幕
总结: MVP变换后viewport变换,所以是MVPV
变换,然后光栅化
,但会出现锯齿!!
2 反走样 Antialiasing
采样
(sampling
) 会产生 瑕疵 artifact
,如
锯齿 Jaggies
空间摩尔纹 Moire
欠采样风扇倒转 Wagon wheel effect
时间- 本质:
信号变化过快(高频),采样速度跟不上(低频)
.
2.1 提前滤波 Pre-Filter
滤波---采样
效果
可以看见在滤波模糊处理后再采样,图像的锯齿少了很多.那么具体该怎么滤波
呢?原理是什么?
2.2 滤波原理
2.2.1 频域与傅里叶变换
根据傅里叶变换
,周期函数,比如方波
可以分解为频率不同
的余弦函数
,如下图
- 空域到频域
F(ω)=∫−∞∞f(x)e−2πiωxdxF(\omega)=\int_{-\infty}^{\infty} f(x) e^{-2 \pi i \omega x} d x F(ω)=∫−∞∞f(x)e−2πiωxdx - 频域到空域
f(x)=∫−∞∞F(ω)e2πiωxdω欧拉公式eix=cosx+isinx\begin{gathered} f(x)=\int_{-\infty}^{\infty} F(\omega) e^{2 \pi i \omega x} d \omega \\ \text { 欧拉公式} e^{i x}=\cos x+i \sin x \end{gathered} f(x)=∫−∞∞F(ω)e2πiωxdω 欧拉公式eix=cosx+isinx
将这些频率不同的余弦函数
画在一起,我们发现用一个固定频率 (图中竖线)
来采样
,对频率越高
的余弦函数,采样后拟合的折线
与原函数差别越大
,这是采样产生artifacts
的原因.
2.2.2 滤波
滤波
就是去掉特定频率
的函数
,那么这个特定频率
是什么
呢?
- 例子
右图
是左边人物图
的频谱图
,中心频率最低
.
- 高通滤波 High-pass filter
去掉中间低频
,我们发现人物图
只有边缘轮廓
,所以高频代表边界
,边界(颜色发生突变的地方)
- 低通滤波 Low-pass filter
去掉外部高频
,我们发现人物图
很模糊
- 上面的
高(低)通滤波
具体是通过卷积
实现的.
2.2.3 卷积 Convolution
图像理论的卷积是如下:
时域的卷积
=频域的乘积
,反之亦然.
(时域)小女孩图片
卷积(低通)滤波器
= (傅里叶变换后频域) 两者相乘 再逆变换
,得到对图像的模糊处理
2.2.4 低通滤波盒子
- 注意上面用了一个
低通滤波器
来模糊
图像
- 对应的
时域图(左)
和频域图(右)
是
如果要得到更模糊的图像
,我们需要时域图盒子变大
(大于3×3的盒子,一个点代表更多信息),即频域图变小
(留下更低频的函数,代表边界
的函数更少).
更极端的理解,如果盒子比屏幕大,等于各处颜色一样,完全模糊.如果盒子是1×1,等于没有模糊.
2.2.4 采样等于重复频率内容***
经过傅里叶变换
的函数X
经过冲击函数P
来采样
,即搬运复制.
密dense采样(频率高
,对应一个三角形的像素密度大
) 和 稀疏sparse采样(频率低
,对应一个三角形的像素密度小
)
总结:为了避免走样alias
,需要
增加采样率
(如增加屏幕分辨率),成本太高
反走样(模糊再采样)
2.3 低通滤波采样
一个关键问题,怎么根据覆盖率
得到上图四种像素值?
2.3.1 超采样 MSAA Multisample anti-aliasing
- 如果一个
像素Pixel
有的部分覆盖率三角形,有的没有覆盖三角形.我们需要将一个像素分成N×N
个点(并没有增加分辨率
),来算覆盖率
- 计算覆盖率
- 结果
- 对应的模糊后的三角形
- 其他反走样方案
MSAA会增加计算量~~~No free lunch!
3 作业 光栅化三角形
- 首先在
main.cpp
复制作业1的Viewing观测变换矩阵
float t = - tan((eye_fov / 360.0) * acos(-1)) * zNear;//t is negative?//float t = tan((eye_fov / 360.0) * acos(-1)) * zNear;float r = t / aspect_ratio;Eigen::Matrix4f perspective;perspective << zNear, 0, 0, 0,0, zNear, 0, 0,0, 0, zNear + zFar, -zNear * zFar,0, 0, 1, 0;Eigen::Matrix4f translate;translate <<1,0,0,0,//-(r + l) / 20,1,0,0,//-(t + b) / 20,0,1,-(zNear + zFar)/2,0,0,0,1;Eigen::Matrix4f scale;scale << 1/r,0,0,0,//2 / (r - l)0,1/t,0,0,//2 / (t - b)0,0,2/(zNear-zFar),0,0,0,0,1;projection = scale * translate * perspective * projection;
- 然后在
rasterizer.cpp
实现判断点是否在三角形内
,找AABB轴向边界盒子
,比较深度(Z-buffer算法)并更新颜色
三个功能 - 判断
点是否在三角形内
static bool insideTriangle(float x, float y, const Vector3f* _v)
{ // TODO : Implement this function to check if the point (x, y) is inside the triangle represented by _v[0], _v[1], _v[2]Vector3f p(x, y, 0);Vector3f ap(p - _v[0]); Vector3f bp(p - _v[1]); Vector3f cp(p - _v[2]); Vector3f ab(_v[1] - _v[0]); Vector3f bc(_v[2] - _v[1]); Vector3f ca(_v[0] - _v[2]);return ap.cross(ab).dot(bp.cross(bc)) > 0 && bp.cross(bc).dot(cp.cross(ca)) > 0;
}
- 找AABB轴向
边界盒子
int x_min1 = v[0].x() < v[1].x() ? v[0].x() : v[1].x();int x_min = x_min1 < v[2].x() ? x_min1 : v[2].x();int x_max1 = v[0].x() > v[1].x() ? v[0].x() : v[1].x();int x_max = x_max1 > v[2].x() ? x_max1 : v[2].x();int y_min1 = v[0].y() < v[1].y() ? v[0].y() : v[1].y();int y_min = y_min1 < v[2].y() ? y_min1 : v[2].y();int y_max1 = v[0].y() > v[1].y() ? v[0].y() : v[1].y();int y_max = y_max1 > v[2].y() ? y_max1 : v[2].y();
- 比较深度并更新颜色 (
Z-buffer算法
)
for (int x = x_min; x <= x_max; x++){for (int y = y_min; y <= y_max; y++){//imag[x][y] = insideTriangle(x + 0.5, y + 0.5, t.v);if (insideTriangle(x + 0.5, y + 0.5, t.v)){auto[alpha, beta, gamma] = computeBarycentric2D(x, y, 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 (z_interpolated < depth_buf[get_index(x, y)]){depth_buf[get_index(x, y)] = z_interpolated;Vector3f point((float)x, (float)y, z_interpolated);Vector3f color = t.getColor();set_pixel(point, color);}}}}
输出
./Rasterizer output.png
4 总结
作业1
和作业2
实现了下面所表示的变换:
- Model
模型
变换 - Viewing
观测
变换 - Projection(
透视
perspective平移
translate缩放
scale)变换和视口
(viewport)变换 光栅化
Rasterize三角形(判断点在三角形内外
,包围盒
,Z-buffer算法
,设置像素颜色
)
光栅化 Rasterization相关推荐
- 计算机图形学三:光栅化-Rasterization
文章目录 什么是光栅化? 像素和屏幕 直线光栅化(Linear Rasterization) DDA数值微分算法 中点Bresenham算法 三角形光栅化(Triangle Rasterization ...
- GAMES101笔记_Lec05~06_光栅化 Rasterization
1 视口变换-从裁剪空间到屏幕空间 Canonical Cube to Screen 1.1 什么是屏幕 What is a screen? 在图形学中,抽象的认为屏幕是一个二维数组,数组中每一个元素 ...
- 计算机图形学【GAMES-101】2、光栅化(反走样、傅里叶变换、卷积)
快速跳转: 1.矩阵变换原理Transform(旋转.位移.缩放.正交投影.透视投影) 2.光栅化(反走样.傅里叶变换.卷积) 3.着色计算(深度缓存.着色模型.着色频率) 4.纹理映射(重心坐标插值 ...
- 渲染 光栅化 光线追踪 着色器 投影视图模型矩阵 未来VR关键技术
渲染介绍得非常详细易懂(强烈建议观看):https://www.zhihu.com/question/31971846/answer/36727962 https://www.zhihu.com/qu ...
- 光栅化(Rasterization)
什么是光栅化? 简单来说,光栅化就是将几何数据经过一系列变换(可以说是连点描边裁剪)最终转换为像素,从而呈现在屏幕上的过程. 光栅化的过程 读取模型的顶点,3个3个的读,因为要画三角形. 将3个顶点两 ...
- 4、计算机图形学——光栅化、抗锯齿、画家算法和深度缓冲算法(Z-buffer)
一.光栅化(Rasterization) 1.1.概念 光栅raster这个词就是德语中屏幕的意思,光栅化的意思就是将图像绘制在屏幕上进行显示. 1.2.三角形光栅化过程简述 首先,为什么要以三角形的 ...
- 谈谈Hybird3D中的光栅化优化
看到空明流转分享了他的SALVIA 0.5.2优化谈,我也来说说Hybird3D中和光栅化相关的一些优化技术. Hybird3D的设计目标是打造一款准实时的软件高质量渲染器,采用了光栅化和光线跟踪混合 ...
- 用C#实现一个简易的软件光栅化渲染器
这是一个用C#+winform实现的软件光栅化渲染器,今天拿出来与大家分享一下,希望能起到抛砖引玉的作用,给新人一点启发(结构比较简单,注释比较详细^_^),也欢迎司机们拍砖指点和交流~ 目的: 巩固 ...
- 图形学基础笔记II:多边形光栅化算法和显卡三角形光栅算法
为什么三角形就够了 实际对于 3D 来说肯定全是基于三角形的 geometry - OpenGL: Is it more efficient to use GL_QUADS or GL_TRIANGL ...
最新文章
- Android runOnUiThread() 方法的使用
- python做一个系统-用python做一个系统监控程序
- 图像处理与计算机视觉资源汇总——论文+代码+教材+视频等等
- QRCode.js -- 用 Javascript 生产二维码
- WordPress添加固定位置的百度分享按钮
- Eclipse 各种快捷键
- js 字符串操作函数有哪些
- nuSVC的使用和解读
- 一个十年SAP CRM老司机对产品主数据的理解
- 我说我精通字符串,面试官竟然问我Java中的String有没有长度限制!?|附视频讲解
- 免费SSL申请:(各大服务商资源综合)- 免费获取
- sqlquerystress
- 【英语学习】【WOTD】farouche 释义/词源/示例
- VS 2019 for Mac 第 3 个预览版发布,新编辑器、Xamarin 开发改进
- SharePoint2010添加webpart找不到内容编辑器
- 红帽安装Oracle步骤
- MIT App Inventor使用与入门教程
- Java日期练习—计算已出生多少天
- 过滤器和拦截器的区别_拦截器和过滤器的区别
- c++ linux pthread函数
热门文章
- 【1252. 奇数值单元格的数目】
- java实现双向RSA + AES加密
- python 编写查字典程序,Python_字典实现简单预约系统
- [Qt5布局] 控件自动填满所在布局框架
- RN-微信钱包页面布局
- 帕特森销售法则(转载)
- 鼠标屏幕取词原理 (VC++)
- SQL2005数据库附加
- [D-VI] my_second_fpga(1位加法器 Verilog HDL抽象级别 modelsim-altrea功能仿真 综合器)
- 数组push后的返回值,容易忽略