Stencil Test: 模板测试
使用模板缓冲区最重要的两个值:当前模板缓冲值和模板参考值;
模板测试主要就是对这两个值使用特定的比较操作:Never,Always,Less,LEqual,Greater,Equal等;
模板测试之后要对模板缓冲区的值进行更新操作,更新操作包括Keep,Zero,Replace,IncrSat,DecrSat,Invert等等;
模板测试之后可以根据结果对模板缓冲区做不同的更新操作,分成多种情况Pass,Fail,ZFail,还有正对正面和背面精确更新操作PassBack,PassFront,FailBack等
CPU(模型数据,法线、顶点位置) GPU
=》顶点着色器 =》 几何阶段【细分着色器 =》 几何着色器】 =》 裁剪 =》 屏幕映射
=》 光栅化阶段【三角形设置 =》 三角形遍历】 =》 early-z =》 片元着色器
=》 逐片元操作【裁剪测试 =》 透明度测试 =》 模板测试 =》 深度测试 =》 透明度混合】
=》 屏幕图像
对当前深度与深度缓冲区进行比较,从而判断是否写入深度
ZWrite
紧接着对颜色缓冲区进行比较,判断是否改变颜色缓冲区中的值
两者差异在于前者有关ZWrite
所谓深度测试,就是针对当前对象在屏幕上(更准确的说是frame buffer)对应的像素点,将对象自身的深度值与当前该像素点缓存的深度值进行比较,如果通过了,本对象在该像素点才会将颜色写入颜色缓冲区,否则不会写入颜色缓冲区。
控制渲染顺序:1. 画家算法;2. Z-Buffer算法
控制Z-Buffer对深度的存储:1.Z Test; 2. Z Write
控制不同类型物体的渲染顺序:1. 透明物体;2.不透明物体;3. 渲染队列
减少overdraw:1. Early-Z;2. Z cull; 3. Z Check
深度缓冲就像颜色缓冲(储存所有的片段颜色:视觉输出)一样,在每个片段中储存了信息,通常与颜色缓冲有同样的长宽。深度缓冲由窗口系统自动创建,它会以16、24或32位float的形式储存它的深度值。在大部分的系统中,深度缓冲的精度都是24位。
z-Buffer中存储的是当前的深度信息,对于每个像素存储一个深度值。
通过Z Write 和 Z Test 来调用 Z-Buffer,实现想要的渲染结果
深度写入包括两种状态: ZWrite On 和 ZWrite Off
只有处在 ZWrite On模式下,并且通过ZTest,才会写入深度缓冲区。
渲染队列分类:
在片元着色器之前,光栅化之后,进行一次深度测试,如果深度测试失败,就不必进行fragment阶段的计算,从而使得性能提升;
但是最终的ZTest不能省略,保证最终的遮挡效果关系结果正确。
模型空间:无深度值
世界空间:存储在Z分量
视图空间:存储在Z分量(线性深度)
裁剪空间:深度缓冲中存储 z/w (透视投影非线性)
屏幕空间:
在实践过程中存储的一般都是非线性深度缓冲区。正确的投影特性的非线性深度方程是和1/z成正比的。这样做是为了在z很近的时候保持高精度,z较远的时候低精度。充分考虑了深度的问题重要性的问题。
1/z函数的图形表示:
深度缓冲区的值不是线性的屏幕空间(他们在视图空间投影矩阵应用之前是线性的)
两个平面或三角形紧密相互平行深度缓冲区不具有足够的精度以至于无法得到哪一个靠前,导致两个平面反复交替顺序的问题。我们将这种现象称作:深度冲突。
不透明物体中:
先对渲染队列进行排序,再对深度值进行排序,从前往后
Subshader中的Pass按顺序从上到下渲染,无论为pass设置了什么队列
两个重要的值:当前深度缓冲值(ZBufferValue)和深度参考值(referenceValue)
Unity中的渲染顺序:先不透明,从前往后;再透明,从后往前
通过Zwrite和Z Test组合使用控制半透明物体的渲染
引入early-z技术提高性能
深度缓冲区中存储的深度值为0到1范围的浮点值,且为非线性
结合上次的flowmap,做了一个流动放大镜的效果,鼠标悬停的位置部分区域有流动,其余区域不动。
浅浅地试了一下XRay效果
贴一下XRay的代码 方便查找:
Shader "Custom/100 learning/MyXRay"
{
Properties
{
_MainTex("Base 2D", 2D) = "white" {}
_XRayColor ("XRay Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
// 利用CGINCLUDE直接定义所有vertex 和 fragment 这样可以共用 struct
CGINCLUDE
#include "UnityCG.cginc"
fixed4 _XRayColor;
struct v2f{
float4 pos:SV_POSITION;
float3 normal:NORMAL;
float3 viewDir:TEXCOORD0;
fixed4 color : COLOR;
};
v2f vertXray(appdata_base v){
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.viewDir = ObjSpaceViewDir(v.vertex);
o.normal = v.normal;
float3 normal = normalize(v.normal);
float3 viewDir = normalize(o.viewDir);
// 通过1 - 计算视角与当前法线的夹角,来对被遮挡的部分赋予颜色权重
float rim = 1 - dot(normal, viewDir);
o.color = _XRayColor * rim;
return o;
}
fixed4 fragXray(v2f i) : SV_Target{
return i.color;
}
sampler2D _MainTex;
float4 _MainTex_ST;
struct v2fRegular{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD;
};
v2fRegular vertRegular(appdata_base v){
v2fRegular o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 fragRegular(v2fRegular i) : SV_Target{
return tex2D(_MainTex, i.uv);
}
ENDCG
// XRay 绘制
Pass{
Tags{
"RenderType" = "Transparent"
"Queue" = "Transparent"
}
Blend SrcAlpha one
ZTest Greater
ZWrite Off
Cull Back
CGPROGRAM
#pragma vertex vertXray
#pragma fragment fragXray
ENDCG
}
// 正常绘制
Pass{
Tags{
"RenderType" ="Opaque"
}
ZTest LEqual
ZWrite On
CGPROGRAM
#pragma vertex vertRegular
#pragma fragment fragRegular
ENDCG
}
}
FallBack Off
}
之后做一下湖水颜色渲染和护盾的切边效果!再想想有什么好玩的。