Unity Shader實(shí)現(xiàn)素描效果
本文實(shí)例為大家分享了Unity Shader實(shí)現(xiàn)素描效果的具體代碼,供大家參考,具體內(nèi)容如下
這是樂(lè)樂(lè)大佬書(shū)里的非真實(shí)渲染,其中的算法還是挺有意思的,感興趣的小伙伴可以試一試。
素描效果基本原理:先將物體進(jìn)行描邊畫(huà)出輪廓,計(jì)算物體的漫反射部分,漫反射越暗表明顏色越暗,然后根據(jù)漫反射的值來(lái)設(shè)置采樣貼圖的權(quán)重。
采樣貼圖:
shader部分:
Shader "Unlit/Sketch" { Properties { _Color("Color",Color) = (1,1,1,1) //貼圖平鋪系數(shù) _TileFactor("TileFactor", Range(0, 10)) = 1 _Hatch0("Hatch0",2D)="white"{} _Hatch1("Hatch1",2D) = "white"{} _Hatch2("Hatch2",2D) = "white"{} _Hatch3("Hatch3",2D) = "white"{} _Hatch4("Hatch4",2D) = "white"{} _Hatch5("Hatch5",2D) = "white"{} //描邊系數(shù) _OutlineFactor("OutlineFactor",Range(0.0,0.1))=0.01 } SubShader { Tags{ "Queue" = "Transparent" } //描邊使用兩個(gè)Pass,第一個(gè)pass沿法線擠出一點(diǎn),只輸出描邊的顏色 Pass { //剔除正面,只渲染背面 Cull Front //關(guān)閉深度寫(xiě)入 ZWrite Off //控制深度偏移,描邊pass遠(yuǎn)離相機(jī)一些,防止與正常pass穿插 Offset 1,1 CGPROGRAM #include "UnityCG.cginc" #pragma vertex vert #pragma fragment frag float _OutlineFactor; struct v2f { float4 pos : SV_POSITION; }; v2f vert(appdata_full v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); //將法線方向轉(zhuǎn)換到視空間 float3 vnormal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal); //將視空間法線xy坐標(biāo)轉(zhuǎn)化到投影空間 float2 offset = TransformViewToProjection(vnormal.xy); //在最終投影階段輸出進(jìn)行偏移操作 o.pos.xy += offset * _OutlineFactor; return o; } fixed4 frag(v2f i) : SV_Target { return float4(0,0,0,1); } ENDCG } Pass { CGPROGRAM #include "UnityCG.cginc" #include "Lighting.cginc" //使用陰影需添加 #include "AutoLight.cginc" #pragma vertex vert #pragma fragment frag //使主要平行光產(chǎn)生陰影 #pragma multi_compile_fwdbase float4 _Color; float _TileFactor; sampler2D _Hatch0; sampler2D _Hatch1; sampler2D _Hatch2; sampler2D _Hatch3; sampler2D _Hatch4; sampler2D _Hatch5; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; //6張依次加深的貼圖 float3 hatchWeights0:TEXCOORD1; float3 hatchWeights1:TEXCOORD2; //聲明陰影 SHADOW_COORDS(4) float3 worldPos:TEXCOORD3; }; v2f vert (appdata_full v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); //平鋪系數(shù)越大,顯示的貼圖越密集 o.uv = v.texcoord* _TileFactor; float3 worldLightDir = normalize(WorldSpaceLightDir(v.vertex)); float3 worldNormal = UnityObjectToWorldNormal(v.normal); //漫反射 float diffuse = max(0, dot(worldLightDir, worldNormal)); o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz ; //六張圖片的權(quán)重 o.hatchWeights0 = float3(0, 0, 0); o.hatchWeights1 = float3(0, 0, 0); //根據(jù)漫反射值計(jì)算權(quán)重,漫反射越暗,線條越密集 float hatchFactor = diffuse * 7.0; if (hatchFactor > 6.0) { } else if (hatchFactor > 5.0) { o.hatchWeights0.x = hatchFactor - 5.0; } else if (hatchFactor > 4.0) { o.hatchWeights0.x = hatchFactor - 4.0; o.hatchWeights0.y = 1.0 - o.hatchWeights0.x; } else if (hatchFactor > 3.0) { o.hatchWeights0.y = hatchFactor - 3.0; o.hatchWeights0.z = 1.0 - o.hatchWeights0.y; } else if (hatchFactor > 2.0) { o.hatchWeights0.z = hatchFactor - 2.0; o.hatchWeights1.x = 1.0 - o.hatchWeights0.z; } else if (hatchFactor > 1.0) { o.hatchWeights1.x = hatchFactor - 1.0; o.hatchWeights1.y = 1.0 - o.hatchWeights1.x; } else { o.hatchWeights1.y = hatchFactor; o.hatchWeights1.z = 1.0 - o.hatchWeights1.y; } //把計(jì)算的陰影傳到fragment中 TRANSFER_SHADOW(o); return o; } fixed4 frag (v2f i) : SV_Target { float4 hatchTex0 = tex2D(_Hatch0, i.uv) * i.hatchWeights0.x; float4 hatchTex1 = tex2D(_Hatch1, i.uv) * i.hatchWeights0.y; float4 hatchTex2 = tex2D(_Hatch2, i.uv) * i.hatchWeights0.z; float4 hatchTex3 = tex2D(_Hatch3, i.uv) * i.hatchWeights1.x; float4 hatchTex4 = tex2D(_Hatch4, i.uv) * i.hatchWeights1.y; float4 hatchTex5 = tex2D(_Hatch5, i.uv) * i.hatchWeights1.z; //漫反射暗色部分權(quán)重越大,白色越少 float4 whiteColor = float4(1, 1, 1, 1)*(1 - i.hatchWeights0.x - i.hatchWeights0.y - i.hatchWeights0.z - i.hatchWeights1.x - i.hatchWeights1.y - i.hatchWeights1.z); float4 hatchColor = hatchTex0 + hatchTex1 + hatchTex2 + hatchTex3 + hatchTex4 + hatchTex5+ whiteColor; //使物體接受陰影 UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos); return float4(hatchColor.rgb*_Color.rgb*atten, 1.0); } ENDCG } } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
微信開(kāi)放平臺(tái)之網(wǎng)站授權(quán)微信登錄功能
本文通過(guò).net實(shí)現(xiàn)的微信開(kāi)放平臺(tái)之網(wǎng)站授權(quán)微信登錄功能,需要的小伙伴一起看看吧2015-09-09詳解C#對(duì)Dictionary內(nèi)容的通用操作
這篇文章主要為大家詳細(xì)介紹了C#對(duì)Dictionary內(nèi)容的一些通用操作,例如:根據(jù)鍵移除信息、根據(jù)值移除信息、根據(jù)鍵獲取值等,需要的可以參考一下2022-06-06WPF實(shí)現(xiàn)類(lèi)似ChatGPT逐字打印效果的示例代碼
前一段時(shí)間ChatGPT類(lèi)的應(yīng)用十分火爆,這類(lèi)應(yīng)用在回答用戶的問(wèn)題時(shí)逐字打印輸出,像極了真人打字回復(fù)消息,本文就來(lái)利用WPF模擬一下這種逐字打印的效果吧2023-08-08c# 數(shù)據(jù)庫(kù)的 sql 參數(shù)封裝類(lèi)的編寫(xiě)
c# 數(shù)據(jù)庫(kù)的 sql 參數(shù)封裝類(lèi)的編寫(xiě)...2007-12-12C#使用Fody實(shí)現(xiàn)監(jiān)控方法執(zhí)行時(shí)間
這篇文章主要為大家詳細(xì)介紹了C#如何使用Fody實(shí)現(xiàn)監(jiān)控方法執(zhí)行時(shí)間,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解下2023-11-11C# 動(dòng)畫(huà)窗體(AnimateWindow)的小例子
C# 動(dòng)畫(huà)窗體(AnimateWindow)的小例子,需要的朋友可以參考一下2013-03-03C#延時(shí)關(guān)閉電腦、取消關(guān)閉電腦操作方法(需管理員權(quán)限)
在C#中,如果想實(shí)現(xiàn)延時(shí)關(guān)閉電腦和取消關(guān)閉的功能,可以有多種方法,下面給大家分享C#延時(shí)關(guān)閉電腦、取消關(guān)閉電腦操作方法,感興趣的朋友一起看看吧2024-06-06