目录:Unity Shader - 知识点目录(先占位,后续持续更新)
原文:ShaderLab: Culling & Depth Testing
版本:2019.1
ShaderLab: Culling & Depth Testing
剔除与深度测试
剔除是一种针对面向相机镜头内的不渲染多边形的优化(针对镜头做剔除的优化)。所有的多边形都有正面与背面。Culling剔除可以将许多不需要渲染的对应剔除掉;如果你有一个Cube立方体,你将永远看不到没有朝向你的面(背面)(因为总是朝着你的面都是正面),所以我们不需要绘制那些背面。因为术语叫:Backface culling(背面剔除)。
(上面那段官方说的太绝对,其实我们有些对象是版透明的,是可以看到双面的,也就是正背面,因为可以透光)
另一个功能是然渲染画面看起来正常的:Depth testing 深度测试。深度测试时确保在场景里离镜头最近的面可以看到。
Syntax
语法
Cull
剔除
Cull Back | Front | Off
控制多边形的那个面应该被剔除(不绘制)
- Back 不渲染多边形的背面(默认)。
- Font 不渲染多边形的正面。这将看到原来被正面遮挡的背面内容。
- Off 禁用剔除,两个面都会被绘制。同于一些特殊的效果。(一般用于绘制比较薄的对象,如:纸)
ZWrite
深度写入
ZWrite On | Off
控制从对象渲染出来的像素是否写入depth buffer深度缓存(默认是开启的)。如果你会值不透明对象,那么设置为开启。如果你绘制的是半透明效果的对象,请开闭它 ZWrite off。往下面看,了解更多。
ZTest
深度测试
ZTest Less | Greater | LEqual | GEqual | Equal | NotEqual | Always
决定深度测试应该如果执行(比较)。默认是 LEqual(小于或等于,Unity的深度是越小的值,表示越靠近镜头,越大的越远离镜头,小于或等于的意思是,当绘制出来的新的片段中的像素,它的深度值比深度缓存中的值小于,或是与缓存值一样,那么久测试通过)。
Offset
偏移(什么偏移:绘制填充式多边形图元的深度值得偏移,具体可以看我下面推荐的文章,U3D这儿说的不是很清楚)
Offset Factor, Units
允许你使用两个参数来指定深度偏移。factor 和 units。 Factor 是缩放相对多边形x或y的Z的最大斜率值,而Units 是缩放深度缓存中最小不可在分的单位值。这将允许你强制将两个处于相同位置的多边形其中一个绘制到另一个上面。例如:Offset 0, -1 将多边形往相机方向拉近,而忽略了多边形斜率值,如果使用 Offset -1, -1 将多边形在处于掠射角时将拉得更近一些。
(可以查看之前写的一篇文章:Offset 的测试,解决简单的z-fighting情况)
Examples
这个对象将仅仅渲染背面:
Shader "Show Insides" {
SubShader {
Pass {
Material {
Diffuse (1,1,1,1)
}
Lighting On
Cull Front
}
}
}
尝试将他应用到一个cube立方体,当你对这个cube旋转会是镜头移动,并留意该cube的显示情况,你会发现好像绘制出错了。这是因为你仅仅看到了cube的里面(背面)那部分。
Transparent shader with depth writes
透明shader与写入深度缓存
通常 semitransparent shaders (半透明着色)都不会写入深度缓存。然而,可能与出现绘制顺序的问题,特别是复杂的非全凸的网格中。如果你想淡入淡出模型,那么在绘制透明对象前先使用shader写入到深度缓存,这种方式也许会有用。
半透明的对象;左:标准透明/漫反射着色器;右:写入深度缓冲区的着色器。
Shader "Transparent/Diffuse ZWrite" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
}
SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
LOD 200
// extra pass that renders to depth buffer only
Pass {
ZWrite On
ColorMask 0
}
// paste in forward rendering passes from Transparent/Diffuse
UsePass "Transparent/Diffuse/FORWARD"
}
Fallback "Transparent/VertexLit"
}
(上面的shader不用去测试了,因为代码版本比较低,UsePass或是Fallback的shader都调整划分了)
Debuggin Normals
调试法线
下面的将会比较有趣了;首先我们渲染一个带有顶点法线光照的对象,然后再用亮粉紫色渲染背面。只要有亮粉紫色出现的地方就是法线被翻转了有误的地方。如果你的一个实际的对象出现了一个光照效果不对的时候,可以尝试使用这个shader来查看法线有无问题。如果有紫粉色出现,那部分就是法线有问题的。
Shader "Reveal Backfaces" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" { }
}
SubShader {
// Render the front-facing parts of the object.
// We use a simple white material, and apply the main texture.
Pass {
Material {
Diffuse (1,1,1,1)
}
Lighting On
SetTexture [_MainTex] {
Combine Primary * Texture
}
}
// Now we render the back-facing triangles in the most
// irritating color in the world: BRIGHT PINK!
Pass {
Color (1,0,1,1)
Cull Front
}
}
}
Glass Culling
玻璃剔除
控制剔除在调试背面信息时是很有用的。如果你的有一些透明对象,你通常都想将它们的背面显示出来。如果你渲染不启用剔除(Cull Off),你得的结果很有可能会出现背面内容覆盖住的正面的内容。
这儿有一个简单的工作于全凸模型(球体,正方体,如,挡风玻璃)。
Shader "Simple Glass" {
Properties {
_Color ("Main Color", Color) = (1,1,1,0)
_SpecColor ("Spec Color", Color) = (1,1,1,1)
_Emission ("Emmisive Color", Color) = (0,0,0,0)
_Shininess ("Shininess", Range (0.01, 1)) = 0.7
_MainTex ("Base (RGB)", 2D) = "white" { }
}
SubShader {
// We use the material in many passes by defining them in the subshader.
// Anything defined here becomes default values for all contained passes.
Material {
Diffuse [_Color]
Ambient [_Color]
Shininess [_Shininess]
Specular [_SpecColor]
Emission [_Emission]
}
Lighting On
SeparateSpecular On
// Set up alpha blending
Blend SrcAlpha OneMinusSrcAlpha
// Render the back facing parts of the object.
// If the object is convex, these will always be further away
// than the front-faces.
Pass {
Cull Front
SetTexture [_MainTex] {
Combine Primary * Texture
}
}
// Render the parts of the object facing us.
// If the object is convex, these will be closer than the
// back-faces.
Pass {
Cull Back
SetTexture [_MainTex] {
Combine Primary * Texture
}
}
}
}
官方没有提供运行效果,这里我就放上来看看吧
上面代码的运行效果:
但上面的图会有个问题,绘制背面的时候因为深度测试将本应该混合的颜色给深度剔除掉了
所以下面我就在第一个绘制背面的Pass加一句:ZWrite Off,如下:
Pass {
Cull Front
ZWrite off // 就加这么一句
SetTexture [_MainTex] {
Combine Primary * Texture
}
}
运行效果: