好久没有写关于shader的文章了,这段时间总结下之前的经验,写几篇关于shader的实践技巧。主要分两个部分,一个部分是unity shader lab ,这一块讲surface shader,unity提供的接口,以及提供的默认指令。第二个部分主要讲cg,为什么要在shader里嵌入cg,而不是其他的图形学相关的编程语言 以及 cg 实用的技巧。

Preface

阅读本文,默认你已经初步了解shader的基本结构,如 Properties , SubShader , pass 。

总结可见性规律

渲染队列规律(默认从小到大)

下面的渲染队列依次是 1000 , 2000 , 2500 , 3000 ,4000
为了方便记忆我将 AlphaTest 的队列排序增加到了 2500,本应是 2450

1
2
3
4
5
Tags { "Queue" = "Background"}
Tags { "Queue" = "Geometry"}
Tags { "Queue" = "AlphaTest+50"}
Tags { "Queue" = "Transparent"}
Tags { "Queue" = "Overlay"}

假设不开启ZWrite,ZTest处于缺省状态(LEqual)状态 或 是ZTest处于任意状态。
默认按照渲染对列的规律开始渲染,如果当前队列较低,则会被高的队列元素覆盖。
如果当前队列较低,则会被高的队列元素覆盖

深度写入是什么?

前置条件当渲染队列需要高于等于参照物,渲染队列规律。
默认规律:所有物体的渲染按照深度(距离摄像头距离),越小的越先渲染。
假设不开启ZWrite,ZTest处于缺省状态(LEqual)状态。近的会先绘制,远的会后绘制,后渲染的就会挡住先渲染的。
ZWrite就是处理深度写入,大概的操作时:当前屏幕已经写过像素,就会跳过当前区域。也就不会出现 后渲染的就会挡住先渲染。

深度测试是什么?

前置条件当渲染队列需要高于等于参照物,渲染队列规律。
只有深度测试成功,才有资格写入深度缓存。也就是说ZWrite的前置条件是ZTest。

Cull

ZTest 有几个可选参数:
Greater,GEqual,Less,LEqual,Equal,NotEqual,Always,Never

默认(缺省)模式为:LEqual 效果:当前位置小于等于参照物,近遮远(最自然)
由上所知 GEqual 的效果为 远遮近

Always 永远绘制在最上
Never 永不绘制

自定义光照模型

默认自定义光照模型
Lighting SurfaceOutput o,half3 lightDir :点到光源的单位向量 ,half3 viewDir:点到摄像机的单位向量 float atten:衰减系数

UnityGI Unity5新特性

下面有四种自定义光照模型的方式,参数列表不同

1
2
3
4
half4 Lighting<Name> (SurfaceOutput s, UnityGI gi); This is used in forward rendering path for light models that are not view direction dependent (e.g. diffuse).
half4 Lighting<Name> (SurfaceOutput s, half3 viewDir, UnityGI gi); This is used in forward rendering path for light models that are view direction dependent.
half4 Lighting<Name>_Deferred (SurfaceOutput s, UnityGI gi, out half4 outDiffuseOcclusion, out half4 outSpecSmoothness, out half4 outNormal); This is used in deferred lighting path.
half4 Lighting<Name>_PrePass (SurfaceOutput s, half4 light); This is used in light prepass (legacy deferred) lighting path.

这里的重点并不是如何去定义光照模型,而是了解 UNITY 5 推出的GI(全局光照)功能。

UnityGI结构体

自定义GI函数

1
half4 Lighting<Name>_GI (SurfaceOutput s, UnityGIInput data, inout UnityGI gi);

可以参照 UnityGlobalIllumination.cginc 这个cg脚本中的 UnityGI_Base 函数 里的 DecodeLightmap与ShadeSHPerPixel 它可以解码 lightmaps 与 SH probes 。物理路径如下:
({unity install path}/Data/CGIncludes/UnityGlobalIllumination.cginc on Windows, /Applications/Unity/Unity.app/Contents/CGIncludes/UnityGlobalIllumination.cginc on Mac)

官方文档

自定义定点动画

自定义定点动画