首页 > 其他分享 >4.Rasterization光栅化(反走样,深度缓存)

4.Rasterization光栅化(反走样,深度缓存)

时间:2023-07-01 13:37:18浏览次数:47  
标签:采样 缓存 Rasterization 走样 卷积 频域 像素 深度

走样Aliasing(锯齿)

采样的广泛应用

  • 采样不仅可以在图片的某个位置,也可以在时间轴上
  • 动画就是一组图在时间的采样

Artifacts(瑕疵、错误)

  • 采样会产生一些Artifacts(瑕疵、错误)
  • 例如:锯齿(图像上的采样)
  • 摩尔纹(删除图像奇数行,再放大成原大小后可得)
  • ”车轮效应“(车轮旋转速度过快,感觉车轮在倒着转)

走样的原因

  1. 信号变化过快(频率高)
  2. 采样频率太慢,跟不上

反走样

模糊Blurring(Pre-Filtering)

  • 模糊操作是在采样前的操作
  • 对原始信号做模糊处理(滤波处理),然后再采样
  • 可以模糊图像边缘,过度更加顺滑

问题:为什么不能先采样,再模糊呢(滤波)?

  • 暂时按下不表

通过频域来分析走样

  • 在频率的角度定义走样:用同样的频率采样两组截然不同的信号,得到的结果无法区分,称之为走样。

  • 对于函数\(y=Asin(\omega x+\varphi)+B\)或\(y=Acos(\omega x+\varphi)+B\)的周期公式是\(T=\frac{2\pi}{|\omega|}\)
  • 对于函数\(y=Atan(\omega x+\varphi)+B\)或\(y=Acot(\omega x+\varphi)+B\)的周期公式是\(T=\frac{\pi}{|\omega|}\)

傅里叶级数展开

  • 任何一个周期函数,都可以被写成一系列正弦余弦和常数的组合。

傅里叶变换

频域展现的走样

  • 在采样频率不变的前提下,假如原信号的周期很长,低于或者接近采样频率,则走样较少
  • 若原信号的周期很短,频率远高于采样频率,则走样很严重

通过频域来分析滤波

定义:频率上删除一系列的特定频率被称滤波

  • 一幅图经过傅里叶变换:从时域到频域的转变,从左图转变到右图
  • 高通滤波
  • 把频率高的信号提取出来,在图像中的表现为:留下了边界
  • 边界:左或者右边,上边和下边发生了突然的变化(信号变化大)
  • 低通滤波
  • 只留下低频的信息,获得相对模糊的图片。
  • 高频低频信息都去除了,留下了中间较为模糊的信号。

卷积Convolution

  • 又称”平均“
  • Flitering滤波=Convolution卷积

  • 滤波器Filter像一个窗口在信号Signal中从头滑动到尾。是一种加权平均。
卷积定理
  • 时域上对两个信号做卷积,相当在频域上对两个信号做乘积。
  • 求卷积:可以把时域信号先傅里叶变换获得频域信号,再做乘积,再傅里叶逆变换,得到信号的卷积
  • 时域上的乘积=频域上的卷积。
例题

  1. 时域图片

  2. 卷积后获得模糊图

  3. 也可以是:先把图片傅里叶变换,获得频域图,

  4. 把卷积操作也做一个傅里叶变换获得卷积和

  5. 两者相乘,获得频域结果图,再逆傅里叶变换获得最终结果。

卷积盒

  • 上图是一个低通滤波器
卷积盒性质

  • 上图左图是一个时域上的白色方块,右图是左图卷积后的频域图
  • 卷积盒子越大,右图片中展示效果则越模糊。
  • 上面3x3的滤波盒子效果为取 9个格子内的平均值
  • 要是64*64大小的盒子则会更失真,更模糊。
  • 反过来,要是盒子足够小不就相当于没有滤波操作。

通过频域来分析采样

  • 定义:重复抽取频域中的内容
  • 上图(c)冲击函数:只在箭头所指方向有值,做采样处理使用。
  • 时域上:原始信号(a)*(c)=(e)
  • 频域上: 对(a)和(c)做傅里叶变换获得(b)

通过频域来分析反走样

  • 上图为频谱信号图,若采样频率高,则可以获得较为清晰完整的信号图
  • 但是采样频率稀疏就会发生频谱重叠。
反走样两种思路
  1. 增加采样频率。(非正式操作,例如换分辨率更高的显示器,像素更小了,采样频率就提升了)
  2. 先做模糊(低通滤波处理),再做采样。

分析模糊处理

  • 把原来的梯形频谱低通滤波处理后,获得新的信号,
  • 再用同样稀疏的采样信号就不会发生采样重叠
  • 时域的表现如上

滤波器

  • 对像素f(x,y)做1像素格子的低通滤波处理(卷积)
  • 取每个像素的中心点进行采样

  • 像素(正方形格子)内的色值平均

更多采样点进行反走样(MSAA)

  • 不是增加分辨率,而是增加了采样点。
  • 对于每个像素,不要仅用一个中间点来判断三角形是否覆盖,而是取4个顶点来分别判断
  • 左图是不采用MSAA的做法,那么这个像素就没有被三角形所覆盖。
  • 右图用四个均匀分布的点来判断,那么有两个点就被三角形覆盖了。
  • 上图采用每像素4个点的三角形覆盖判断
  • 在具体的计算中,对于每个像素,fragment shader只需要算一次。
  • 对每个采样点赋以颜色值,最终将四个采样点的颜色平均就可以得到像素的颜色。
  • 这样一来,就可以取到较好的抗锯齿效果。
  • 计算量不会有太大变化,但是存储量则要*4(因为多了四个采样点,每个采样点也要存颜色值)。
  • 下图展示了原始图像和运用了MSAA的图像,可以看到抗锯齿的效果还是比较明显的:

其他抗锯齿方案

参考链接https://zhuanlan.zhihu.com/p/78407475

FXAA(快速近似抗锯齿Fast Apporximate AA)
  • 图像后期处理,把图像边界找到,再用其他像素替换。
TAA( Temporal AA)
  • 复用上一帧的样本,对本帧进行图像的优化处理。
SSAA和DLSS超采样反走样(SSAA)
  • 是一种支持抗锯齿的方法。它的做法也很简单:假设我们的屏幕像素为800600,那么我们只需要将渲染的texture扩大4倍(16001200),然后再把相邻像素值做一个过滤(比如平均等)得到最终的图像就可以解决这个问题了。利用该方法确实可以从根本上消除锯齿,但是这种方法大大提高了存储空间和计算量,所以一般不会使用这种技术。

  • DLSS是通过深度学习,将放大分辨率后的图片进行滤波处理。其余原理与SSAA相似。

深度缓冲(Z-buffering)

何为深度

  • 深度其实就是该象素点在3d世界中距离摄象机的距离(绘制坐标),深度缓存中存储着每个象素点(绘制在屏幕上的)的深度值!深度值(Z值)越大,则离摄像机越远。

为什么需要深度?

  • 在不使用深度测试的时候,如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为后绘制,会把距离近的物体覆盖掉,这样的效果并不是我们所希望的。而有了深度缓冲以后,绘制物体的顺序就不那么重要了,都能按照远近(Z值)正常显示,这很关键。

例子

  • 图中有很多物体,需要按先后、前后的关系放置到图中
  • 例如把最远的摆上,再把近的物体摆放在远的前面(先画山,再画草地,再画树)

  • 特殊情况:两两覆盖
  • 不能使用画家算法来渲染图,所以引入了z-buffering。

Z-Buffering

性质

  • 又名深度缓冲,深度缓存
  • 处理不了透明物体

具体实现

  • 保存每一个像素的深度(z_value)
  • 在加载时,同时缓存了
    • 帧缓存,像素的颜色信息
    • 深度缓存,每个像素的深度信息
  • 前提:相机在原点,并且是往-Z方向看到物体的,所以Z一直是负的。z越小离摄像机越近,z越大,离摄像机越远。

算法流程

  • 假设开始时,深度是无限远的
  • 对任意一个三角形,光栅化成像素后。
  • 对任意像素,若该像素深度小于在zbuffer【x,y】中的值,则把帧信息更新到framebuffer[x,y]中,深度数组zbuffer[x,y]也要更新。

效果流程图

  • R表示无限远的深度,红色格子深度为5,5<R,所以更新了颜色和深度。
  • 蓝色的三角形中像素深度小于5的,则更新framebuffer和zbuffer数组,若大于等于5,则不更新。

标签:采样,缓存,Rasterization,走样,卷积,频域,像素,深度
From: https://www.cnblogs.com/oOLzYOo/p/17519153.html

相关文章

  • 3.Rasterization光栅化(三角形光栅化)
    前情提要模型变换视图变换投影变换(正交投影、透视投影)物体会缩放到\([-1,1]^3\)的立方体内接下来,我们需要把物体放画到屏幕上,即光栅化屏幕有一组像素像素的多少(分辨率)一种光栅成像设备Raster在德语中就表示屏幕所以光栅化就是把物体画在屏幕上的意思像素Pixe......
  • 缓存击穿、缓存雪崩、缓存穿透
    怎么防止缓存击穿:在实际应用中,我们会在程序和数据库之间增加一个缓存层,一方面是为了提升数据的检索效率,提升程序的性能,另一方面是为了缓解数据库的一个并发压力,缓存击穿是因为客户端恶意发送一些大量不存在的key的请求,由于访问的key,对应的数据本身不存在,所以每一次必然都会穿透到......
  • 四种语言刷算法之LRU 缓存
    力扣146. LRU缓存1、Ctypedefstruct{intkey;intval;UT_hash_handlehh;}LRUCache;LRUCache*usr=NULL;intsize=0;LRUCache*lRUCacheCreate(intcapacity){size=capacity;returnusr;}intlRUCacheGet(LRUCache*obj,intke......
  • Redis实战(黑马点评--商户查询缓存)
    为什么使用缓存 添加商户缓存 ShopController层/***根据id查询商铺信息*@paramid商铺id*@return商铺详情数据*/@GetMapping("/{id}")publicResultqueryShopById(@PathVariable("id")Longid){returnshopService.qu......
  • 【SpringBoot】redis keys命令被禁用,spring缓存 @CacheEvict报异常
     背景项目使用springboot整合redis做缓存,代码中使用spring的缓存注解配置缓存策略。在jarvis上部署时接入了公司分布式redis平台代替本地的redis。结果测试的时候,新增一条记录时报了错,提示  ERRunknowncommand'keys' 。经排查发现问题原因:新增记录的函数上有@C......
  • celery 之 celery介绍架构和安装、celery执行异步任务、包结构celery、celery执行
    目录一、celery介绍架构和安装1、celery:分布式的异步任务框架,主要用来做:2、celery框架,原理3、celery架构4、安装celery5、celery不支持win,所以想再win上运行,需要额外安装eventlet二、celery执行异步任务基本使用1再虚拟环境中装celery和eventlet2写个py文件,实例化得到app对象......
  • 11celery介绍架构和安装,celery执行异步任务,包结构celery,celery执行延迟任务和定时任务
    1celery介绍架构和安装#celery:分布式的异步任务框架,主要用来做: -异步任务-延迟任务-定时任务---》如果只想做定时任务,可以不使用celery,有别的选择#celery框架,原理1)可以不依赖任何服务器,通过自身命令,启动服务(内部支持socket)2)celery服务为为其他项目......
  • 使用guava的cache实现缓存
    一、maven<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.......
  • 10redis列表操作,其他操作,redis管道,django中使用redis,django缓存,序列化json和pickle,cel
    字符串和字节转换的两种方式#字符串和字节转换的两种方式 -decode,encode-直接类型转换-bytes格式的16进制,2进制,10进制的显示#字符串需要用encode,bytes格式需要用decode,但是有时候忘了#可以直接进行强转b1=bytes(s,encoding='utf-8') print(......
  • django缓存的使用
    缓存:可以把django中的一个变量(数据),存放到某个位置,下次还可以取出来之前用过:默认放在:内存中,其实可以放在文件中,数据库,redis。。。。fromdjango.core.cacheimportcachecache.set('key','value',5)#存放值res=cache.get('key')#取值通过配置,控制存放在哪,只要如下写,就会......