unity5, custom PBS shader
unity5中引入了基于物理著色(PBS)的Standard shader。由于這種著色器通過調(diào)節(jié)參數(shù)和貼圖可逼真模擬各種硬質(zhì)表面,所以不必再像unity4時代那樣需要對各種質(zhì)感材質(zhì)單獨編寫著色器,而且能得到更好的效果(參考:http://docs.unity3d.com/Manual/shader-StandardShader.html)。這種“萬能著色器”仿佛給人一種不再需要自己編寫著色器的假象,但做游戲跟做虛擬現(xiàn)實不一樣,除了真實性,還要追求趣味性和藝術夸張。所以老古語不過時:沒有使用自定義著色器的游戲,不是好游戲。
但自己實現(xiàn)PBS是很困難的,如果我們想既繼承Standard shader的PBS特性又加入自己的定制效果,最好我們的自定義shader能在Standard shader的基礎上進行編寫,即實現(xiàn)自定義PBS著色器(custom PBS shader)。
由于是新東西,資料不全,google了一整天也沒能找到現(xiàn)成方法,unity官方文檔中對此完全沒有作說明(在surface shader自定義光照模型 部分只給了不帶PBS的例子),unity論壇里有多個帖子問到類似問題,但都沒有滿意解答。最后在下面兩個連接里找到了一點兒線索:
http://forum.unity3d.com/threads/for-those-in-u5-beta-is-pbr-really-that-good.283867/page-3#post-1886525
http://blogs.unity3d.com/2014/10/29/physically-based-shading-in-unity-5-a-primer/ (文章下面?MIG 的提問)
此線索是:“
from the release notes for beta 12:
- Shaders: Surface shaders can use physically based shading now; the same as Standard shader uses.
- Use "Standard" lighting function, and "SurfaceOutputStandard" output structure.
- Do an #include "UnityPBSLighting.cginc" in your shader to get it.
- Default options require shader model 3.0, so add a "#pragma target 3.0" too.
”
然后又結(jié)合了UnityPBSLighting.cginc中的源代碼(注1),當然,只是從UnityPBSLighting.cginc中拷貝一些代碼出來(而不是修改它),最后終于把custom PBS shader試驗成功了。
注1:UnityPBSLighting.cginc這個文件在哪兒?有三個途徑獲得:
(1),在 http://docs.unity3d.com/Manual/SL-SurfaceShaderLighting.html 中寫道:“file inside Unity (
下圖第一個球用的是Standard shader,第二個球用的是“將法線當作顏色值”的自定義shader(不帶PBS),第三個球是今天的試驗成果:在Standard shader的PBS基礎上添加了“將法線當作顏色值”效果的雜交shader。
第一個球的shader用的是unity(version 5.0.1f1 Personal)里新建shader時生成的默認shader:
Shader?"Custom/NewShader"?{
????Properties?{
????????_Color?("Color",?Color)?=?(1,1,1,1)
????????_MainTex?("Albedo?(RGB)",?2D)?=?"white"?{}
????????_Glossiness?("Smoothness",?Range(0,1))?=?0.5
????????_Metallic?("Metallic",?Range(0,1))?=?0.0
????}
????SubShader?{
????????Tags?{?"RenderType"="Opaque"?}
????????LOD?200
????????
????????CGPROGRAM
????????//?Physically?based?Standard?lighting?model,?and?enable?shadows?on?all?light?types
????????#pragma?surface?surf?Standard?fullforwardshadows
????????//?Use?shader?model?3.0?target,?to?get?nicer?looking?lighting
????????#pragma?target?3.0
????????sampler2D?_MainTex;
????????struct?Input?{
????????????float2?uv_MainTex;
????????};
????????half?_Glossiness;
????????half?_Metallic;
????????fixed4?_Color;
????????void?surf?(Input?IN,?inout?SurfaceOutputStandard?o)?{
????????????//?Albedo?comes?from?a?texture?tinted?by?color
????????????fixed4?c?=?tex2D?(_MainTex,?IN.uv_MainTex)?*?_Color;
????????????o.Albedo?=?c.rgb;
????????????//?Metallic?and?smoothness?come?from?slider?variables
????????????o.Metallic?=?_Metallic;
????????????o.Smoothness?=?_Glossiness;
????????????o.Alpha?=?c.a;
????????}
????????ENDCG
????}?
????FallBack?"Diffuse"
}
在此基礎上參照UnityPBSLighting.cginc中的源代碼將光照模型以自定義光照模型的形式暴露出來,得到下面等價shader:
(這里需要注意的是,一般自定義光照模型只要實現(xiàn)一個 Lightning+自定義光照模型名稱 的函數(shù)即可,但是對于PBS shader來說,要實現(xiàn)自定義光照模型還要多寫一個?Lightning+自定義光照模型名稱_GI 的函數(shù)。)
Shader?"Custom/customPBS"?{
??????Properties?{
????????_Color?("Color",?Color)?=?(1,1,1,1)
????????_MainTex?("Albedo?(RGB)",?2D)?=?"white"?{}
????????_Glossiness?("Smoothness",?Range(0,1))?=?0.5
????????_Metallic?("Metallic",?Range(0,1))?=?0.0
????}
????SubShader?{
????????Tags?{?"RenderType"="Opaque"?"MyReplaceTag"="Other"}
????????LOD?200
????????
????????CGPROGRAM
????
????????//?Physically?based?Standard?lighting?model,?and?enable?shadows?on?all?light?types
????????#pragma?surface?surf?MyCustomStandard?fullforwardshadows
????????//?Use?shader?model?3.0?target,?to?get?nicer?looking?lighting
????????#pragma?target?3.0
????????#include?"UnityPBSLighting.cginc"
????????inline?void?LightingMyCustomStandard_GI?(
????????????SurfaceOutputStandard?s,
????????????UnityGIInput?data,
????????????inout?UnityGI?gi)
????????{
????????????gi?=?UnityGlobalIllumination?(data,?s.Occlusion,?s.Smoothness,?s.Normal);
????????}
????????inline?half4?LightingMyCustomStandard?(SurfaceOutputStandard?s,?half3?viewDir,?UnityGI?gi)
????????{
????????????s.Normal?=?normalize(s.Normal);
????????????half?oneMinusReflectivity;
????????????half3?specColor;
????????????s.Albedo?=?DiffuseAndSpecularFromMetallic?(s.Albedo,?s.Metallic,?/*out*/?specColor,?/*out*/?oneMinusReflectivity);
????????????//?shader?relies?on?pre-multiply?alpha-blend?(_SrcBlend?=?One,?_DstBlend?=?OneMinusSrcAlpha)
????????????//?this?is?necessary?to?handle?transparency?in?physically?correct?way?-?only?diffuse?component?gets?affected?by?alpha
????????????half?outputAlpha;
????????????s.Albedo?=?PreMultiplyAlpha?(s.Albedo,?s.Alpha,?oneMinusReflectivity,?/*out*/?outputAlpha);
????????????half4?c?=?UNITY_BRDF_PBS?(s.Albedo,?specColor,?oneMinusReflectivity,?s.Smoothness,?s.Normal,?viewDir,?gi.light,?gi.indirect);
????????????c.rgb?+=?UNITY_BRDF_GI?(s.Albedo,?specColor,?oneMinusReflectivity,?s.Smoothness,?s.Normal,?viewDir,?s.Occlusion,?gi);
????????????c.a?=?outputAlpha;
????????????
????????????return?c;
????????}
????????sampler2D?_MainTex;
????????struct?Input?{
????????????float2?uv_MainTex;
????????};
????????half?_Glossiness;
????????half?_Metallic;
????????fixed4?_Color;
????????void?surf?(Input?IN,?inout?SurfaceOutputStandard?o)?{
????????????//?Albedo?comes?from?a?texture?tinted?by?color
????????????fixed4?c?=?tex2D?(_MainTex,?IN.uv_MainTex)?*?_Color;
????????????o.Albedo?=?c.rgb;
????????????//?Metallic?and?smoothness?come?from?slider?variables
????????????o.Metallic?=?_Metallic;
????????????o.Smoothness?=?_Glossiness;
????????????o.Alpha?=?c.a;
????????}
????????
????????
????????ENDCG
????}?
????FallBack?"Diffuse"
}
?
上面shader和默認shader效果完全一樣,但是由于暴露出來光照模型(即上面的LightingMyCustomStandard函數(shù)),便使得我們可以在光照模型層次上對其進行修改,實現(xiàn)出自己的變種shader效果。
例如下面shader,就是在LightingMyCustomStandard中插入一行代碼,實現(xiàn)前面圖中第三個球的效果:
Shader?"Custom/customPBSAndShowNormalAsColor"?{
????Properties?{
????????_Color?("Color",?Color)?=?(1,1,1,1)
????????_MainTex?("Albedo?(RGB)",?2D)?=?"white"?{}
????????_Glossiness?("Smoothness",?Range(0,1))?=?0.5
????????_Metallic?("Metallic",?Range(0,1))?=?0.0
????}
????SubShader?{
????????Tags?{?"RenderType"="Opaque"?}
????????LOD?200
????????
????????CGPROGRAM
????
????????//?Physically?based?Standard?lighting?model,?and?enable?shadows?on?all?light?types
????????#pragma?surface?surf?MyCustomStandard?fullforwardshadows
????????//?Use?shader?model?3.0?target,?to?get?nicer?looking?lighting
????????#pragma?target?3.0
????????#include?"UnityPBSLighting.cginc"
????????inline?void?LightingMyCustomStandard_GI?(
????????????SurfaceOutputStandard?s,
????????????UnityGIInput?data,
????????????inout?UnityGI?gi)
????????{
????????????gi?=?UnityGlobalIllumination?(data,?s.Occlusion,?s.Smoothness,?s.Normal);
????????}
????????inline?half4?LightingMyCustomStandard?(SurfaceOutputStandard?s,?half3?viewDir,?UnityGI?gi)
????????{
????????????s.Normal?=?normalize(s.Normal);
????????????half?oneMinusReflectivity;
????????????half3?specColor;
????????????s.Albedo?=?DiffuseAndSpecularFromMetallic?(s.Albedo,?s.Metallic,?/*out*/?specColor,?/*out*/?oneMinusReflectivity);
????????????//?shader?relies?on?pre-multiply?alpha-blend?(_SrcBlend?=?One,?_DstBlend?=?OneMinusSrcAlpha)
????????????//?this?is?necessary?to?handle?transparency?in?physically?correct?way?-?only?diffuse?component?gets?affected?by?alpha
????????????half?outputAlpha;
????????????s.Albedo?=?PreMultiplyAlpha?(s.Albedo,?s.Alpha,?oneMinusReflectivity,?/*out*/?outputAlpha);
????????????half4?c?=?UNITY_BRDF_PBS?(s.Albedo,?specColor,?oneMinusReflectivity,?s.Smoothness,?s.Normal,?viewDir,?gi.light,?gi.indirect);
????????????c.rgb?+=?UNITY_BRDF_GI?(s.Albedo,?specColor,?oneMinusReflectivity,?s.Smoothness,?s.Normal,?viewDir,?s.Occlusion,?gi);
????????????c.a?=?outputAlpha;
????????????
????????????c.rgb*=s.Normal?*1.5;//added?by?wantnon
????????????return?c;
????????}
?
????????sampler2D?_MainTex;
????????struct?Input?{
????????????float2?uv_MainTex;
????????};
????????half?_Glossiness;
????????half?_Metallic;
????????fixed4?_Color;
????????void?surf?(Input?IN,?inout?SurfaceOutputStandard?o)?{
????????????//?Albedo?comes?from?a?texture?tinted?by?color
????????????fixed4?c?=?tex2D?(_MainTex,?IN.uv_MainTex)?*?_Color;
????????????o.Albedo?=?c.rgb;
????????????//?Metallic?and?smoothness?come?from?slider?variables
????????????o.Metallic?=?_Metallic;
????????????o.Smoothness?=?_Glossiness;
????????????o.Alpha?=?c.a;
????????}
????????
????????
????????ENDCG
????}?
????FallBack?"Diffuse"
}?
當然,如果不需要在光照模型的層次上對unity自帶的PBS shader進行定制,是沒有必要這么麻煩的。
比如就拿上面這個customPBS+ShowNormalAsColor來說,其實沒必要深入到光照模型層次上去實現(xiàn),下面shader就可以實現(xiàn)基本相同的效果:
(其中藍字是在前面Custom/NewShader基礎上新增的語句)
Shader?"Custom/NewShaderAndShowNormalAsColor"?{
????Properties?{
????????_Color?("Color",?Color)?=?(1,1,1,1)
????????_MainTex?("Albedo?(RGB)",?2D)?=?"white"?{}
????????_Glossiness?("Smoothness",?Range(0,1))?=?0.5
????????_Metallic?("Metallic",?Range(0,1))?=?0.0
????}
????SubShader?{
????????Tags?{?"RenderType"="Opaque"?}
????????LOD?200
????????
????????CGPROGRAM
????????//?Physically?based?Standard?lighting?model,?and?enable?shadows?on?all?light?types
????????#pragma?surface?surf?Standard?fullforwardshadows
????????//?Use?shader?model?3.0?target,?to?get?nicer?looking?lighting
????????#pragma?target?3.0
????????sampler2D?_MainTex;
????????struct?Input?{
????????????float2?uv_MainTex;
float3?worldNormal;//ref:?http://wiki.unity3d.com/index.php?title=Shader_Code
????????};
????????half?_Glossiness;
????????half?_Metallic;
????????fixed4?_Color;
????????void?surf?(Input?IN,?inout?SurfaceOutputStandard?o)?{
????????????//?Albedo?comes?from?a?texture?tinted?by?color
????????????fixed4?c?=?tex2D?(_MainTex,?IN.uv_MainTex)?*?_Color;
?? ?c.rgb*=IN.worldNormal;
????????????o.Albedo?=?c.rgb;
????????????//?Metallic?and?smoothness?come?from?slider?variables
????????????o.Metallic?=?_Metallic;
????????????o.Smoothness?=?_Glossiness;
????????????o.Alpha?=?c.a;
????????}
????????ENDCG
????}?
????FallBack?"Diffuse"
}
轉(zhuǎn)載于:https://www.cnblogs.com/wantnon/p/4395286.html
總結(jié)
以上是生活随笔為你收集整理的unity5, custom PBS shader的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 子元素增加margin-top会增加给父
- 下一篇: 020.day20 线程概述 多线程优缺