Unity Shader 學習之旅之SurfaceShader
unity
shader
圖形圖像
若是大地的每一個角落都充滿了光明 誰還須要星星,誰還會 在夜裏凝望 尋找遙遠的安慰——江河html
官方文檔函數
1、工做原理
sureface表面着色器至關於unity在頂點片元着色器的基礎上進一步的封裝。當咱們定義一個「surface function」後,能夠經過unity已經封裝好的的結構體「SurfaceOutput」等直接獲取須要的數據,如紋理,法線,光滑度等學習
2、結構體
2.1標準output結構體
- struct SurfaceOutput
- {
- fixed3 Albedo;
- fixed3 Normal;
- fixed3 Emission;
- half Specular;
- fixed Gloss;
- fixed Alpha;
- };
2.2Unity5 output結構體
unity5中表面着色器使用基於物理的光照模型。內建Standard和StantardSpecular光照模型使用以下兩種結構體:ui
- struct SurfaceOutputStandard
- {
- fixed3 Albedo;
- fixed3 Normal;
- half3 Emission;
- half Metallic;
- half Smoothness;
- half Occlusion;
- fixed Alpha;
- };
- struct SurfaceOutputStandardSpecular
- {
- fixed3 Albedo;
- fixed3 Specular;
- fixed3 Normal;
- half3 Emission;
- half Smoothness;
- half Occlusion;
- fixed Alpha;
- };
3、SurfaceShader編譯指令
SurfaceShader被放置在 CGPROGRAM---ENDCG語塊之間,須要注意如下兩點:spa
- 必須放置在SubShader語塊中,不能在Pass語塊中,SurfaceShader會自主編譯成多個Pass
- 經過使用 #pragma surface ... 來代表這是一個SurfaceShader
- #pragma surface surfaceFunction lightModel [optionalparams]
3.1必要參數
- surfaceFuncton:這就是咱們在編譯指令中指定的表面着色器Cg函數。能夠經過 void surf (Input IN, inout SurfaceOutput o) 這種形式定義。其中input是咱們定義的結構體,包含該函數須要的數據信息。
- lightMode:光照模型能夠使用內建的基於物理的 Standard 和StandardSpecular。也能夠使用非物理的Lambert BlinnPhong。這幾種類型能夠直接經過在編譯指令中指定,無需在本身實現。
-
- Standard 光照模型使用SurfaceOutputStandard output結構體
-
- StandardSpecular 光照模型使用SurfaceOutputStandardSpecular output結構體
-
- Lambert和BlinnPhong 光照模型使用 SurfaceOutput output結構體
3.2可選參數
經過指定可選參數[optionalparams],能夠讓surfaceshader表現出更豐富的效果,如霧效,半透明,陰影等。可選參數具體類型可參考文首給出的 官方文檔 查閱。3d
3.3示例
示例1:使用內置Lambert光照模型的表面着色器code
- Shader "Example/Rim" {
- Properties {
- _MainTex ("Texture", 2D) = "white" {}
- _BumpMap ("Bumpmap", 2D) = "bump" {}
- _RimColor ("Rim Color", Color) = (0.26,0.19,0.16,0.0)
- _RimPower ("Rim Power", Range(0.5,8.0)) = 3.0
- }
- SubShader {
- Tags { "RenderType" = "Opaque" }
- CGPROGRAM
- #pragma surface surf Lambert
- struct Input {
- float2 uv_MainTex;
- float2 uv_BumpMap;
- float3 viewDir;
- };
- sampler2D _MainTex;
- sampler2D _BumpMap;
- float4 _RimColor;
- float _RimPower;
- void surf (Input IN, inout SurfaceOutput o) {
- o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
- o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
- half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));
- o.Emission = _RimColor.rgb * pow (rim, _RimPower);
- }
- ENDCG
- }
- Fallback "Diffuse"
- }
示例2:使用可選參數的表面着色器,經過指定decal:blend,該shader會表現出半透明貼畫的效果。orm
- Shader "Example/Decal" {
- Properties {
- _MainTex ("Base (RGB)", 2D) = "white" {}
- }
- SubShader {
- Tags { "RenderType"="Opaque" "Queue"="Geometry+1" "ForceNoShadowCasting"="True" }
- LOD 200
- Offset -1, -1
-
- CGPROGRAM
- #pragma surface surf Lambert decal:blend
-
- 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
- }
- }