TA入门笔记(十五)
参考
may佬《技术美术百人计划》
冯乐乐《Unity Shader入门精要》
Unity Shader - 模板简单测试 - 实现镂空/遮罩、描边
图形3.1 深度与模板测试
模板测试
定义
渲染管线
模板测试是逐片元操作中的一部分
片元经过逐片元操作的各种测试之后被输出到帧缓冲区,最后输出到屏幕上
逐片元操作阶段高度可配置,不可编程
- Pixel Ownership Test:控制对当前屏幕的使用权限,如在unity中只对game窗口和scene窗口中的像素有权限,其他的窗口部分会被剔除掉
- Scissor Test:裁剪测试,自己定义在窗口中渲染哪些部分,默认是全部渲染
- Alpha Test:透明度测试,设定透明度阈值,大于该阈值的片元通过测试,只能实现不透明效果和全透明效果
- Stencil Test:模板测试
- Depth Test:深度测试
- Blending :透明度混合,在这里来实现半透明效果
逻辑
通过一定条件来判断对该片元或片元属性执行抛弃操作还是保留操作
概念
- 模板缓冲区为屏幕上的每个像素点保存一个无符号整数值(通常8位),这个值的具体意义视程序的具体应用而定
- 在渲染的过程中,将这个值(stencilBufferValue)与一个预先设定的参考值(referenceValue)相比较,根据比较的结果来决定是否更新相应的像素点的颜色值,通过则更新,否则不更新
- 模板测试发生在透明度测试(alpha test)之后,深度测试(depth test)之前
语法表示
模板结构
ComparisonFunction 比较操作
函数 | 作用 |
---|---|
Greater | 相当于“>”,即当左边>右边,模板测试通过,渲染像素 |
GEqual | 相当于“>=”,即当左边>=右边,模板测试通过,渲染像素 |
Less | 相当于“<”,即当左边<右边,模板测试通过,渲染像素 |
LEqual | 相当于“<=”,即当左边<=右边,模板测试通过,渲染像素 |
Equal | 相当于“=”,即当左边=右边,模板测试通过,渲染像素 |
NotEqual | 相当于“!=”,即当左边!=右边,模板测试通过,渲染像素 |
Always | 不管公式两边为何值,模板测试总是通过,渲染像素 |
Never | 不管公式两边为何值,模板测试总是不通过,像素被抛弃 |
StencilOperation 更新值
函数 | 作用 |
---|---|
Keep | 保留当前缓冲里的内容,即stencilBufferValue不变 |
Zero | 将0写入缓冲,即stencilBufferValue变为0 |
Replace | 将参考值写入缓冲,即将referenceValue赋值给stencilBufferValue |
IncrSat | stencilBufferValue加1,超过255时保留为255 |
DecrSat | stencilBufferValue减1,小于0时保留为0 |
Invert | stencilBufferValue按位取反 |
IncrWrap | stencilBufferValue加1,超过255时变成0(然后继续自增) |
DecrWrap | stencilBufferValue减1,小于0时变成255(然后继续自减) |
总结
- 使用模板缓冲区最重要的两个值:当前模板缓冲值(stencilBufferValue)和模板参考值(referenceValue)
- 模板测试主要就是对这两个值使用特定的比较操作:Never,Always,Less ,LEqual,Greater,Equal等
- 模板测试之后要对模板缓冲区的值(stencilBufferValue)进行更新操作,更新操作包括:Keep,Zero,Replace,IncrSat,DecrSat,Invert等
- 模板测试之后可以根据结果对模板缓冲区做不同的更新操作,比如模板测试成功操作Pass,模板测试失败操作Fail,深度测试失败操作ZFail,还有正对正面和正对背面的精确更新操作PassBack,PassFront,FailBack等
- 利用模板测试的特性和其他测试或图形算法结合可以实现其他的效果:描边,多边形填充,反射区域控制、shadow volume阴影渲染等
深度测试
进行遮挡关系的判断
定义
渲染管线
深度测试同样在逐片元阶段,位于模板测试之后
逻辑
概念
深度测试就是针对当前对象在帧缓冲区中对应的像素点,将对象自身的深度值与当前该像素点缓存的深度值进行比较,如果通过了,本对象在该像素点才会将颜色写入颜色缓冲区,否则不会写入颜色缓冲
发展
- 画家算法:从后往前渲染,当多个物体被遮挡时会产生大量overdraw
Z-Buffer 深度缓冲区
- 深度缓冲在每个片段中储存了信息,通常和颜色缓冲有相同的宽度和高度
- 深度缓冲由系统自动创建,以16、24或32位float储存深度值,在大部分系统中是24位
- z-buffer中存储的是当前的深度信息,每个像素存储一个深度值
- 通过Z Write和Z Test来调用Z-Buffer,实现想要的效果
ZWrite 深度写入
深度写入包括两种状态:ZWrite On与ZWrite Off
深度写入开启且深度测试通过的情况下,物体的深度会被写入深度缓冲区
ZTest分为通过和不通过两种情况,ZWrite分为开启和关闭两种情况的话,一共就是四种情况:
- ZTest通过,ZWrite On:写入深度缓冲区,写入颜色缓冲区
- ZTest通过,ZWrite Off:不写入深度缓冲区,写入颜色缓冲区
- ZTest不通过,ZWrite On:不写入深度缓冲区,不写入颜色缓冲区
- ZTest不通过,ZWrite Off:不写入深度缓冲区,不写入颜色缓冲区
ZTest 比较操作
ZTest 状态 | 描述 |
---|---|
Greater | 深度大于当前缓存则通过 |
GEqual | 深度大于等于当前缓存则通过 |
Less | 深度小于当前缓存则通过 |
LEqual | 深度小于等与当前缓存则通过 |
Equal | 深度等于当前缓存则通过 |
NotEqual | 深度不等于当前缓存则通过 |
Always | 深度不论如何都通过 |
Never | 深度不论如何都不通过 |
- 默认状态为ZWrite On,ZTest LEqual,深度缓存初始值为无穷大
渲染队列
Unity内置5种渲染队列,按照渲染顺序从先到后进行排序,队列数越小的越先渲染,队列数越大的越后渲染
- Background(1000)最早被渲染的队列
- Geometry(2000)不透明物体的渲染队列,大多数物体都在此队列,也是Unity Shader默认的渲染队列
- Alpha Test(2450)有透明通道,需要进行透明度测试的物体的队列,比在Geometry中更有效
- Transparent(3000)半透明物体的队列,需要进行透明度混合的物体在此队列,渲染顺序为从后往前
- Overlay(4000)最后被渲染的队列,用来实现一些叠加效果如镜头光晕、屏幕贴片等
Early-Z技术
传统的渲染管线中,ZTest是在Blending阶段进行的,之前经过片元着色器计算之后却没有通过深度测试的片元会被舍弃,这会造成大量无用计算,不利于性能的提升
现代GPU中运用了Early-Z的技术,在Vertex阶段和Fragment阶段之间(光栅化之后,片元着色器处理之前)进行一次深度测试,如果深度测试失败,就不必进行fragment阶段的计算了,因此在性能上会有很大的提升
- 最终的ZTest仍会进行,用于确保最终的遮挡关系正确
- 前一次主要为了裁剪,后一次主要为了检查
深度值
在将物体从观察空间转换到裁剪空间时,需要将深度值转换到视锥体近平面和远平面之间即[0,1],由于人眼的特性,这个变换是非线性的,例如:
Fdepth=1/z−1/near1/far−1/nearF_{depth}=\frac{1/z-1/near}{1/far-1/near}Fdepth=1/far−1/near1/z−1/near
离得近的时候看得清楚,因此分配较高的深度范围
当两个物体过于接近且深度值精度不足无法区分两个物体的前后顺序时,会出现深度冲突的问题,在两个平面之间不停切换
使用非线性的深度值还有利于在有限精度的深度缓冲区内给近处的物体足够高的精度来防止产生深度冲突;而远处的物体即使发生深度冲突也不会看得很清楚
深度冲突无法完全避免,但可以通过一些技巧来减轻或完全防止深度冲突在场景中出现:
- 使物体间不要离得太近以至于三角形重叠
- 尽可能把近平面设置地远一些
- 放弃一些性能来提高深度值的精度,现在的显卡可以支持32位的深度值
总结
- 使用深度缓冲区最重要的两个值:当前深度缓冲值(ZBufferValue)和深度参考值(referenceValue),并通过比较操作获取理想渲染效果
- Unity中的渲染顺序:先渲染不透明物体,顺序是从前往后;再渲染透明物体,顺序是从后往前
- 通过Zwrite 和Z Test组合使用控制半透明物体的渲染
- 引入early-z技术后的深度测试相关的渲染流程,z-call、z-check
- 深度缓冲区中存储的深度值为0到1范围的浮点值,且为非线性
作业
模板测试
仿照案例制作的效果
使用模板测试方式制作的模型描边:
使用两个pass,第一个pass绘制模型,第二个pass将模型空间下的顶点按法线方向挤出,再通过模板测试剔除重叠的部分
// 模型的模板
Stencil{ref 1Comp alwaysPass replaceZFail replace}
//描边的模板
Stencil{ref 0Comp equal}
//描边Pass
Pass {Stencil{ref 0Comp equal}ZTest alwaysCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct a2v{float4 vertex : POSITION;float3 normal : NORMAL;};half4 _OutlineColor;fixed _OutlineWidth;float4 vert (a2v v) : SV_POSITION {float4 pos = UnityObjectToClipPos(v.vertex);fixed3 vNormal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);//将法线转换至观察空间fixed2 offset = TransformViewToProjection(vNormal.xy);pos.xy += offset * _OutlineWidth ;return pos;}fixed4 frag(): SV_Target { return _OutlineColor;}ENDCG}
深度测试
仿照案例制作的X光效果
通过深度混合制作的水流屏障效果
TA入门笔记(十五)相关推荐
- 深度学习入门笔记(五):神经网络的编程基础
欢迎关注WX公众号:[程序员管小亮] 专栏--深度学习入门笔记 声明 1)该文章整理自网上的大牛和机器学习专家无私奉献的资料,具体引用的资料请看参考文献. 2)本文仅供学术交流,非商用.所以每一部分具 ...
- 深度学习入门笔记(五):神经网络的学习
专栏--深度学习入门笔记 推荐文章 深度学习入门笔记(一):机器学习基础 深度学习入门笔记(二):神经网络基础 深度学习入门笔记(三):感知机 深度学习入门笔记(四):神经网络 深度学习入门笔记(五) ...
- 机器学习入门笔记(五):决策树
文章目录 一.决策树模型与学习 1.1 决策树模型 1.2 决策树与 if-then 规则 1.3 决策树与条件概率分布 1.4 决策树的学习 二.特征选择 2.1 信息增益 2.2 例题:利用信息增 ...
- python复制指定字符串_python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)...
python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...
- [转]周易入门三十五问答
周易入门三十五问答 http://mt.sohu.com/20150714/n416782382.shtml 1.问:何谓<周易>? 答:<周易>是我国古代哲学.自然科学与社会 ...
- windows内核开发学习笔记十五:IRP结构
windows内核开发学习笔记十五:IRP结构 IRP(I/O Request Package)在windows内核中,有一种系统组件--IRP,即输入输出请求包.当上层应用程序需要访问底层输入输 ...
- Inno Setup入门(十五)——Inno Setup类参考(1)
Inno Setup入门(十五)--Inno Setup类参考(1) nno setup脚本能够支持许多的类,这些类使得安装程序的功能得到很大的加强,通过对这些类的使用,将会创建出许多让人惊奇的安装程 ...
- Polyworks脚本开发学习笔记(十五)-用Python连接Polyworks的COM组件
Polyworks脚本开发学习笔记(十五)-用Python连接Polyworks的COM组件 用Polyworks脚本开发,没有高级语言的支持,功能难免单一,一些比较复杂的交互实现不了,界面和报告也很 ...
- OpenGL入门学习(十五)
OpenGL入门学习[十五] 这次讲的所有内容都装在一个立方体中,呵呵. 呵呵,绘制一个立方体,简单呀,我们学了第一课第二课,早就会了. 先别着急,立方体是很简单,但是这里只是拿立方体做一个例子,来说 ...
- Reflex WMS入门系列十五:Reflex系统上对已经Confirm的Receipt能继续做收货么?
Reflex WMS入门系列十五:Reflex系统上对已经Confirm的Receipt能继续做收货么? 如下的Receipt已经完成了收货,并且已经confirm了, Cfm(confirm)栏位被 ...
最新文章
- HDU5017(模拟退火算法)
- JVM运行时数据区---方法区(演变和垃圾回收)
- C++类型转换(翻译自cplusplus)
- linux shell脚本字符串连接符,学习Linux shell脚本中连接字符串的方法
- API Gateway简介
- java的int、char、long、float、double对byte的转换,在通信的时候会用到
- mysql反模式_MongoDB报表实例 -- 标签成员方案
- SAS线缆为什么这样多
- 47不用加减乘除做加法
- 机房收费系统重构版:照葫芦画瓢
- 「学习记录」《数值分析》第二章计算实习题(Python语言)
- Qt之QListView使用
- 为什么这本搜索引擎营销的书畅销呢?
- MySQL的图形化安装
- java冒泡排序 代码简单明了
- word文档如何画线条流程图_Word中流程图如何画 手把手教你制作!
- 调试3G模块语音通话
- 英语语法之句子成分(造句)
- 交换机最多可以接几个_【技术】详解一个交换机能带动多少个网络监控摄像头?...
- 如何有效查看电脑显卡对应的CUDA版本