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"
}

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

 

  现在,我们来做个完全一样的,但是使用我们自己的光照模型,而不是内建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 * );
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 * );
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...

 

卡通渐变(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 * );
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...

 

简单镜面(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 (, dot (s.Normal, lightDir)); float nh = max (, dot (s.Normal, h));
float spec = pow (nh, 48.0); half4 c;
c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * );
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 * );
c.a = s.Alpha;
return c;
} inline fixed4 LightingStandard_SingleLightmap (SurfaceOutput s, fixed4 color) {
half3 lm = DecodeLightmap (color);
return fixed4(lm, );
} inline fixed4 LightingStandard_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade) {
half3 lm = lerp (DecodeLightmap (indirectOnlyColor), DecodeLightmap (totalColor), indirectFade);
return fixed4(lm, );
} 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, );
} 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) =
_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 * ); 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, );
} inline fixed4 LightingTonemapped_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade) {
half3 lm = TonemapLight(lerp (DecodeLightmap (indirectOnlyColor), DecodeLightmap (totalColor), indirectFade));
return fixed4(lm, );
} 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, );
} 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"
}

最新文章

  1. .Net程序员之Python基础教程学习----字符串的使用 [Second Day]
  2. Perl Print Win32 Console Windows 控制台 print Unicode 问题
  3. bzoj 1070: [SCOI2007]修车 费用流
  4. Extjs表单控件入门
  5. <p></p>标签为什么不能包含块级标签?还有哪些特殊的HTML标签?
  6. ssh整合之一spring的单独运行环境
  7. Spring Cloud Feign的文件上传实现
  8. 牛客网 2018年东北农业大学春季校赛 L题 wyh的天鹅
  9. Bumped!【最短路】(神坑
  10. LeetCode - Maximum Frequency Stack
  11. JAVA多线程Thread与Runnable
  12. js实现表单提交 onsubmit
  13. openfire聊天记录插件
  14. 20155204 2016-2017-2 《Java程序设计》第7周学习总结
  15. Shell 将两个文件按列合并
  16. Gym 101334E Exploring Pyramids(dp+乘法原理)
  17. strops()
  18. 在scrollview中双击定点放大的代码
  19. 标准结构篇:2)O型橡胶密封圈
  20. ATM购物作业

热门文章

  1. ubuntu 安装eclipse,adt,android sdk,离线
  2. python中的浅拷贝与赋值不同
  3. 向量时钟算法简介——本质类似MVCC
  4. 【源码】c#编写的安卓客户端与Windows服务器程序进行网络通信
  5. SortedSet有序集合类型
  6. jsp开发知识
  7. DBAccess
  8. SPOJ GSS1 静态区间求解最大子段和
  9. 删除ubuntu旧版本内核
  10. Python的平凡之路(4)