转载

Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples

Surface Shader 光照例子

这里有一些自定义光照模型和Surface Shaders的例子。通常的Surface Shader例子在这里。

由于延迟光照在某些自定义的逐材质光照模型中表现得并不好,在下面大多数例子中,我们让shader只编译到正向渲染中。

漫反射(Diffuse)

让我们以使用内建Lambert光照模型的shader作为开始吧!

Shader "Example/Diffuse Texture" {   Properties {  _MainTex ("Texture", 2D) = "white" {}   }   SubShader {  Tags { "RenderType" = "Opaque" }  CGPROGRAM  #pragma surface surf Lambert  struct Input {   float2 uv_MainTex;  };  sampler2D _MainTex;  void surf (Input IN, inout SurfaceOutput o) {   o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;  }  ENDCG   }   Fallback "Diffuse" } 

下面是使用一张纹理贴图和不使用一张真实的纹理贴图的样子(此场景中有一个方向光)

Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples

现在,我们来做个完全一样的,但是使用我们自己的光照模型,而不是内建Lambert光照模型。 Surface Shader光照模型 仅是一些我们需要编写的函数。这里有一个简单的Lambert光照模型。注意到只有CGPROGRAM部分发生了改变,周边的shader代码是完全一样的:

Shader "Example/Diffuse Texture" {  Properties {   _MainTex ("Texture", 2D) = "white" {}  }  SubShader {  Tags { "RenderType" = "Opaque" }  CGPROGRAM    #pragma surface surf SimpleLambert    half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) {     half NdotL = dot (s.Normal, lightDir);     half4 c;     c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2);     c.a = s.Alpha;     return c;    }  struct Input {   float2 uv_MainTex;  };  sampler2D _MainTex;  void surf (Input IN, inout SurfaceOutput o) {   o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;  }  ENDCG  }  Fallback "Diffuse" } 

所以我们的简单漫反射光照模型就是 LightingSimpleLambert 函数。它通过计算表面法线和光线方向的点积来计算光照,然后应用光照衰减和颜色。

环绕漫反射(Diffuse Wrap)

这里是环绕漫反射——漫反射光照的修改版,即照明环绕在物体的边缘。它对用来仿照表面下散射效果很有用。因为只是CGPROGRAM 部分发生了改变,老生常谈一次,周边的shader代码就省略了:

 ...ShaderLab code... CGPROGRAM #pragma surface surf WrapLambert half4 LightingWrapLambert (SurfaceOutput s, half3 lightDir, half atten) {  half NdotL = dot (s.Normal, lightDir);  half diff = NdotL * 0.5 + 0.5;  half4 c;  c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);  c.a = s.Alpha;  return c; } struct Input {  float2 uv_MainTex; }; sampler2D _MainTex;  void surf (Input IN, inout SurfaceOutput o) {  o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } ENDCG ...ShaderLab code... 

Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples

卡通渐变(Toon Ramp)

下面是一个"渐变(Ramp)"光照模型。它使用一张渐变纹理来定义表面怎样对光线和法线的夹角做出反应。这能用来实现多种效果,包括卡通光照。

...ShaderLab code... CGPROGRAM #pragma surface surf Ramp sampler2D _Ramp; half4 LightingRamp (SurfaceOutput s, half3 lightDir, half atten) {  half NdotL = dot (s.Normal, lightDir);  half diff = NdotL * 0.5 + 0.5;  half3 ramp = tex2D (_Ramp, float2(diff)).rgb;  half4 c;  c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);  c.a = s.Alpha;  return c; } struct Input {  float2 uv_MainTex; }; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutput o) {  o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } ENDCG ...ShaderLab code... 

Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples

Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples

简单镜面(Simple Specular)

下面是一个简单镜面光照模型。这对于内置的BlinnPhong实际所做的内容来说非常简单。我们把它放在这来说明它是如何工作的。

  ...ShaderLab code... CGPROGRAM #pragma surface surf SimpleSpecular half4 LightingSimpleSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {  half3 h = normalize (lightDir + viewDir);  half diff = max (0, dot (s.Normal, lightDir));  float nh = max (0, dot (s.Normal, h));  float spec = pow (nh, 48.0);  half4 c;  c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * 2);  c.a = s.Alpha;  return c; } struct Input {  float2 uv_MainTex; }; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutput o) {  o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } ENDCG ...ShaderLab code... 

解码光照贴图(Decoding Lightmaps)

我们将以这样一个shader作为开始:它模仿内置的光照贴图解码工作,使用Unity自带的DecodeLightmap函数解码lightmap中储存的数据信息,以及使用自带的 UNITY_DIRBASIS宏定义方向光照贴图(Directional lightmap)的基本向量: 

Shader "Example/Standard Lightmap Decoding" {  Properties {   _MainTex ("Texture", 2D) = "white" {}  }  SubShader {   Tags { "RenderType" = "Opaque" }   CGPROGRAM   #pragma surface surf Standard   half4 LightingStandard (SurfaceOutput s, half3 lightDir, half atten) {    half NdotL = dot (s.Normal, lightDir);    half4 c; c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2);    c.a = s.Alpha;    return c;   }   inline fixed4 LightingStandard_SingleLightmap (SurfaceOutput s, fixed4 color) {    half3 lm = DecodeLightmap (color);    return fixed4(lm, 0);   }   inline fixed4 LightingStandard_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade) {    half3 lm = lerp (DecodeLightmap (indirectOnlyColor), DecodeLightmap (totalColor), indirectFade);    return fixed4(lm, 0);   }   inline fixed4 LightingStandard_StandardLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal) {    UNITY_DIRBASIS    half3 lm = DecodeLightmap (color);    half3 scalePerBasisVector = DecodeLightmap (scale);    if (surfFuncWritesNormal)    {     half3 normalInRnmBasis = saturate (mul (unity_DirBasis, s.Normal));     lm *= dot (normalInRnmBasis, scalePerBasisVector);    }    return fixed4(lm, 0);   }   struct Input {    float2 uv_MainTex;   };   sampler2D _MainTex;   void surf (Input IN, inout SurfaceOutput o) {    o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;   }   ENDCG   }  Fallback "Diffuse" } 

现在,让我们为光照贴图中储存的光添加些色调映射(tone mapping):

Shader "Example/Tonemapped Lightmap Decoding" {  Properties {   _MainTex ("Texture", 2D) = "white" {}   _Gain ("Lightmap tone-mapping Gain", Float) = 1   _Knee ("Lightmap tone-mapping Knee", Float) = 0.5   _Compress ("Lightmap tone-mapping Compress", Float) = 0.33  }  SubShader {   Tags { "RenderType" = "Opaque" }   CGPROGRAM   #pragma surface surf Tonemapped   half4 LightingTonemapped (SurfaceOutput s, half3 lightDir, half atten) {    half NdotL = dot (s.Normal, lightDir);    half4 c; c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * 2); c.a = s.Alpha;    return c;   }   half _Gain;   half _Knee;   half _Compress;   inline half3 TonemapLight (half3 i) {    i *= _Gain;    return (i > _Knee)? (((i - _Knee)*_Compress)+_Knee): i;   }   inline fixed4 LightingTonemapped_SingleLightmap (SurfaceOutput s, fixed4 color) {    half3 lm = TonemapLight(DecodeLightmap (color));    return fixed4(lm, 0);   }   inline fixed4 LightingTonemapped_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade) {    half3 lm = TonemapLight(lerp (DecodeLightmap (indirectOnlyColor), DecodeLightmap (totalColor), indirectFade));    return fixed4(lm, 0);   }   inline fixed4 LightingTonemapped_StandardLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal) {    UNITY_DIRBASIS    half3 lm = TonemapLight(DecodeLightmap (color));    half3 scalePerBasisVector = DecodeLightmap (scale);    if (surfFuncWritesNormal)    {     half3 normalInRnmBasis = saturate (mul (unity_DirBasis, s.Normal));     lm *= dot (normalInRnmBasis, scalePerBasisVector);    }    return fixed4(lm, 0);   }   struct Input {    float2 uv_MainTex;   };   sampler2D _MainTex;   void surf (Input IN, inout SurfaceOutput o) {    o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;   }   ENDCG  }  Fallback "Diffuse" } 
正文到此结束
Loading...