光栅化
光栅化 Rasterize
将经过观测变换后在
Rasterize == Drawing onto the screen
屏幕
一个二维数组,每个元素表示一个像素(pixel)
初步认知:一个pixel内部颜色不会变化
像素的范围在(0,0) 到 (width-1,height-1)
一个像素的中心是(x+0.5,y+0.5)
变换 3D立方体到2D屏幕
z值用于zbuffer
目前只考虑x,y方向的拉伸
拉伸原本为2的高度,变为 width或者height
将原本在中心的原点移动到左下角
可以得到视口变换矩阵
物体到屏幕的变换#
像素化
将组成物体的多个多边形(目前以三角形为例)用屏幕上的像素来表示
一个像素与一个三角形的关系#
即观测像素的中心点是否在三角形内
绘制方法:离散化#
离散化:将连续的变换值,变为离散的间距相等的点
for(int x = start ; x < end ; x++) //x++就是离散过程
{
for(int y = start; y< end ; y++)
{
//pixel(x,y) 是否在三角形内部
if(inside(x,y,tri))
//着色
color[x][y] = f(x,y);
}
}
判断一个像素中心点是否在三角形内#
一个三角形P1P2P0,像素中心点Q
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 a (_v[1].x()-_v[0].x(),_v[2].x()-_v[0].x(),_v[0].x()-x);
Vector3f b (_v[1].y()-_v[0].y(),_v[2].y()-_v[0].y(),_v[0].y()-y);
//叉乘
Vector3f c (a.y()*b.z()-a.z()*b.y(),a.z()*b.x()-a.x()*b.z(),a.x()*b.y()-a.y()*b.x());
if(abs(c.z()) < 1e-2) return false;
//点(x,y)的重心坐标
Vector3f res (1.f-(c.x()+c.y())/c.z(),c.y()/c.z(),c.x()/c.z());
if(res.x() < 0 || res.y() < 0 || res.z() < 0) return false;
return true;
}
包围盒 -- 约束可以光栅化的范围#
包围整个待光栅化物体的范围,可以避免对不在这个区域的像素进行光栅化操作
//vector<tria> v(3) 表示三角形的三个顶点
int minx, maxx, miny, maxy;
minx = std::min(v[0].x(), std::min(v[1].x(), v[2].x()));
maxx = std::max(v[0].x(), std::max(v[1].x(), v[2].x()));
miny = std::min(v[0].y(), std::min(v[1].y(), v[2].y()));
maxy = std::max(v[0].y(), std::max(v[1].y(), v[2].y()));
反走样
解决边缘锯齿效果
原始信号变化的太快,采样频率小于变化频率,导致走样现象的出现
滤波 -- 模糊#
傅里叶变换 -- 时域到频域
一般图片经过傅里叶变换后,中间低频信息较多(亮),四周的高频信息较少(暗)
图像在频域中的高频信号一般可以表示出图像内容的边界(高通滤波:取出低频信号)
图像在频域中的低频信号一般会将图像模糊 (低通滤波:去掉高频信号)
滤波的效果 == 卷积的效果 == 平均的效果
- 时域的卷积 == 频域的乘积
- 时域的乘积 == 频域的卷积
为了能达到图像模糊的效果,可以采用这样的方法,对一个图片上的像素点,可以将其周围的3×3的像素值的平均值写入当这个像素点到达了模糊效果。
走样的原因 -- 频率上的解释#
在时域上,采样频率小,说明采样间隔大。而采样结果相当于时域上原始信号和采样信号的乘积,对应频域上就是原始信号频率和采样频率的卷积。
当时域上采样间隔大,那么频域上的间隔就会减小,导致每个采样信号下的原始信号频谱出现重叠的现象导致走样。
重叠部分的一般为高频信息
解决走样的方法#
- 增加采样率 -- 分辨率
- 对原始信号先模糊再采样
模糊#
模糊 == 低通滤波 == 移除一个信号的高频信息 == 去除频域中重叠区域
使用一定大小的块,对当前图像信号进行卷积操作。
最直观的块就是一个像素大小的块,将这个块作为卷积盒,对图像(以三角形为例)进行卷积。
如果以一个像素大小的块作为box filter,那么这个像素块的颜色就是三角形覆盖住的部分和未覆盖部分的平均值。
MSAA#
对原始的每个像素再划分比如2×2,然后对这4个格子判断每个格子的中心点是否在三角形内,然后着色,这样就可以算出一个像素的平均颜色。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律