創文章如需轉載請註明:轉載自風宇沖Unity3D教程學院
Shader第十四講 Surface Shader
用Shader來實現光照是比較複雜的,有不同的光類型,不同的陰影選項,不同的Render Path(forward和Deferred)。 Unity只是把光照模型封裝處理了,Shader的代碼還是用CG/HLSL編寫的。
例一:最簡單的Surface Shader
- Shader "Custom/T_3_0" {
- Properties {
- _MainTex ("Base (RGB)", 2D) = "white" {}
- }
- SubShader {
- CGPROGRAM
- #pragma surface surf Lambert
- sampler2D _MainTex;
- struct Input {
- float2 uv_MainTex;
- } ;
- void surf (Input IN, inout SurfaceOutput o) {
- half4 c = tex2D (_MainTex, IN.uv_MainTex);
- o.Albedo = c.rgb;
- o.Alpha = c.a;
- }
- ENDCG
- }
- }
表面處理函數從頂點處理函數(這裡自動頂點處理)接收參數Input IN,輸出SurfaceOutput o至光照模型(這裡是Lambert)。這裡我們就做了三件事:(1)通過uv取得了貼圖對應uv的顏色c (2)把c.rgb賦給o.Albedo (3) 把c.a賦給o.Alpha這就完成了。之後讓任一物體使用該Shader,則不管加什麼光都能正確顯示。真的很簡單!
表面處理函數surf的輸入及輸出
(1)輸入
- struct Input {
- float2 uv_MainTex;
- float3 viewDir;
- float4 anyName:COLOR;
- float4 screenPos;
- float3 worldPos;
- float3 worldRefl;
- } ;
uv_MainTex: uvviewDir: 入視角screenPos:裁剪空間位置worldPos:世界空間位置
(2)輸出
- struct SurfaceOutput {
- half3 Albedo;
- half3 Normal;
- half3 Emission;
- half Specular;
- half Gloss;
- half Alpha;
- };
Albedo:漫反射顏色Normal: 法線Emission:自發光顏色Specular:鏡面反射係數Gloss:Alpha:透明值更多的參數請參考文檔
Surface Shader參數Surface Shader可以通過加參數實現額外的控制,例如加頂點處理函數,alpha混合等。注意:如果使用的光照模型是Unity內建的Lambert或者BlinnPhong:alpha混合,alpha混合等功能必須使用Surface Shader參數。之前例如AlphaTest Greater 0.3 等代碼就不能再加了。如果加了的話,光照失效,物體為一片漆黑。如果使用的光照模型是自訂光照模型:只要在surf中給o.Alpha正常賦值(如賦貼圖顏色的a值),那麼之前例如AlphaTest Greater 0.3 等代碼依然可以照常使用。具體相關代碼可以參考下一講中的代碼。
(1)alpha混合直接加參數Alpha即可
#pragma surface surf BlinnPhong alpha
(2)alphatest
加入一個變數,這裡起名為_Cutoff, 然後在#pragma surface結尾處加上alphatest:_Cutoff。
效果是alpha值大於_Cutoff時,才會輸出顏色
- Shader "Custom/T_3_0" {
- Properties {
- _MainTex ("Base (RGB)", 2D) = "white" {}
- _Cutoff ("Alpha cutoff", Range(0,1)) =
0.5
- }
- SubShader {
- CGPROGRAM
- #pragma surface surf Lambert alphatest:_Cutoff
- sampler2D _MainTex;
- struct Input {
- float2 uv_MainTex;
- } ;
- void surf (Input IN, inout SurfaceOutput o) {
- half4 c = tex2D (_MainTex, IN.uv_MainTex);
- o.Albedo = c.rgb;
- o.Alpha = c.a;
- }
- ENDCG
- }
- }
(3)頂點函數
例:臃腫的模型
實現方法,將頂點向法線方向延伸一段距離
- Shader "Example/Normal Extrusion" {
- Properties {
- _MainTex ("Texture", 2D) = "white" {}
- _Amount ("Extrusion Amount", Range(-1,1)) = 0.5
- }
- SubShader {
- Tags { "RenderType" = "Opaque" }
- CGPROGRAM
- #pragma surface surf Lambert vertex:vert
- struct Input {
- float2 uv_MainTex;
- };
- float _Amount;
- void vert (inout appdata_full v) {
- v.vertex.xyz += v.normal * _Amount;
- }
- sampler2D _MainTex;
- void surf (Input IN, inout SurfaceOutput o) {
- o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
- }
- ENDCG
- }
- Fallback "Diffuse"
- }
(4)finalcolor
finalcolor:ColorFunction
對顏色輸出作最後的更改
- Shader
"Example/Tint Final Color" {
- Properties
{
- _MainTex
("Texture",
2D) =
"white"
{}
- _ColorTint
("Tint",
Color) = (1.0,
0.6,
0.6,
1.0)
- }
- SubShader
{
- CGPROGRAM
- #pragma
surface surf Lambert
finalcolor:mycolor
- struct
Input {
- float2
uv_MainTex;
- };
- fixed4
_ColorTint;
-
void
mycolor (Input IN, SurfaceOutput o, inout fixed4 color)
- {
- //在這裡對最後輸出的顏色color進行修改
- color
*= _ColorTint;
- }
- sampler2D
_MainTex;
- void
surf (Input IN, inout SurfaceOutput o) {
- o.Albedo
= tex2D (_MainTex, IN.uv_MainTex).rgb;
- }
- ENDCG
- }
- }
更多的參數請參考文檔