以下代碼來源於第三方插件。
Feature代碼:
1 using System.Collections.Generic; 2 using UnityEngine; 3 using UnityEngine.Experimental.Rendering.Universal; 4 using UnityEngine.Rendering; 5 using UnityEngine.Rendering.Universal; 6 7 //[ExecuteInEditMode] 8 public class FurRenderFeature : ScriptableRendererFeature 9 { 10 [System.Serializable] 11 public class FilterSettings 12 { 13 // TODO: expose opaque, transparent, all ranges as drop down 14 public RenderQueueType RenderQueueType; 15 public LayerMask LayerMask = 1; 16 public string[] PassNames; 17 18 public FilterSettings() 19 { 20 RenderQueueType = RenderQueueType.Opaque; 21 LayerMask = ~0; 22 PassNames = new string[] {"FurRendererBase", "FurRendererLayer"}; 23 } 24 } 25 26 public static FurRenderFeature instance; 27 28 /// <summary> 29 /// This function is called when the object becomes enable and active. 30 /// </summary> 31 /// 32 [System.Serializable] 33 public class PassSettings 34 { 35 public string passTag = "FurRenderer"; 36 [Header("Settings")] 37 public bool ShouldRender = true; 38 [Tooltip("Set Layer Num")] 39 [Range(1, 200)]public int PassLayerNum = 20; 40 [Range(1000, 5000)] public int QueueMin = 2000; 41 [Range(1000, 5000)] public int QueueMax = 5000; 42 public RenderPassEvent PassEvent = RenderPassEvent.AfterRenderingSkybox; 43 44 public FilterSettings filterSettings = new FilterSettings(); 45 } 46 47 public class FurRenderPass : ScriptableRenderPass 48 { 49 string m_ProfilerTag; 50 RenderQueueType renderQueueType; 51 private PassSettings settings; 52 private FurRenderFeature furRenderFeature = null; 53 public List<ShaderTagId> m_ShaderTagIdList = new List<ShaderTagId>(); 54 private ShaderTagId shadowCasterSTI = new ShaderTagId("ShadowCaster"); 55 private FilteringSettings filter; 56 public Material overrideMaterial { get; set; } 57 public int overrideMaterialPassIndex { get; set; } 58 59 public FurRenderPass(PassSettings setting, FurRenderFeature render,FilterSettings filterSettings) 60 { 61 m_ProfilerTag = setting.passTag; 62 string[] shaderTags = filterSettings.PassNames; 63 this.settings = setting; 64 this.renderQueueType = filterSettings.RenderQueueType; 65 furRenderFeature = render; 66 //過濾設定 67 RenderQueueRange queue = new RenderQueueRange(); 68 queue.lowerBound = setting.QueueMin; 69 queue.upperBound = setting.QueueMax; 70 filter = new FilteringSettings(queue,filterSettings.LayerMask); 71 if (shaderTags != null && shaderTags.Length > 0) 72 { 73 foreach (var passName in shaderTags) 74 m_ShaderTagIdList.Add(new ShaderTagId(passName)); 75 } 76 } 77 78 // This method is called before executing the render pass. 79 // It can be used to configure render targets and their clear state. Also to create temporary render target textures. 80 // When empty this render pass will render to the active camera render target. 81 // You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>. 82 // The render pipeline will ensure target setup and clearing happens in an performance manner. 83 public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) 84 { 85 } 86 87 // Here you can implement the rendering logic. 88 // Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers 89 // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html 90 // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline. 91 public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) 92 { 93 SortingCriteria sortingCriteria = (renderQueueType == RenderQueueType.Transparent) 94 ? SortingCriteria.CommonTransparent 95 : renderingData.cameraData.defaultOpaqueSortFlags; 96 CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag); 97 //============================================================= 98 //draw objects(e.g. reflective wet ground plane) with lightmode "MobileSSPRWater", which will sample _MobileSSPR_ColorRT 99 DrawingSettings baseDrawingSetting, layerDrawingSetting; 100 //BaseLayer DrawingSetting 101 if (m_ShaderTagIdList.Count > 0) 102 baseDrawingSetting = CreateDrawingSettings(m_ShaderTagIdList[0], ref renderingData, 103 renderingData.cameraData.defaultOpaqueSortFlags); 104 else return; 105 if(m_ShaderTagIdList.Count > 1) 106 layerDrawingSetting = CreateDrawingSettings(m_ShaderTagIdList[1], ref renderingData, 107 renderingData.cameraData.defaultOpaqueSortFlags); 108 else return; 109 float inter = 1.0f / settings.PassLayerNum; 110 //BaseLayer 111 cmd.Clear(); 112 cmd.SetGlobalFloat("_FUR_OFFSET", 0); 113 context.ExecuteCommandBuffer(cmd); 114 context.DrawRenderers(renderingData.cullResults,ref baseDrawingSetting,ref filter); 115 //TransparentLayer 116 for(int i = 1; i < settings.PassLayerNum; i++) 117 { 118 cmd.Clear(); 119 cmd.SetGlobalFloat("_FUR_OFFSET", i * inter); 120 context.ExecuteCommandBuffer(cmd); 121 context.DrawRenderers(renderingData.cullResults,ref layerDrawingSetting,ref filter); 122 } 123 CommandBufferPool.Release(cmd); 124 } 125 126 /// Cleanup any allocated resources that were created during the execution of this render pass. 127 public override void FrameCleanup(CommandBuffer cmd) 128 { 129 } 130 } 131 public PassSettings settings = new PassSettings(); 132 FurRenderPass m_ScriptablePass; 133 134 public override void Create() 135 { 136 instance = this; 137 FilterSettings filter = settings.filterSettings; 138 m_ScriptablePass = new FurRenderPass(settings, this, filter); 139 // Configures where the render pass should be injected. 140 m_ScriptablePass.renderPassEvent = settings.PassEvent; 141 } 142 143 // Here you can inject one or multiple render passes in the renderer. 144 // This method is called when setting up the renderer once per-camera. 145 public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) 146 { 147 renderer.EnqueuePass(m_ScriptablePass); 148 } 149 }
毛皮shader:
1 Shader "LXShader/Other/MultiPassFurModified" 2 { 3 Properties 4 { 5 [Header(Macro)] 6 [Toggle(_TANGENT_TO_WORLD)] _TangentToWorld("Tangent To World", Float) = 0 7 [Toggle(_GI_ON)] _GI_ON("GIOn", Float) = 0 8 [Toggle(_RECEIVE_SHADOWS)] _RECEIVE_SHADOWS("Receive Shadow", Float) = 0 9 [KeywordEnum(On,Off)] _NORMALMAP_URP("Mormal Map", Float) = 0 10 [Header(Main)] 11 [MainColor]_Color("Color", Color) = (1,1,1,1) 12 _MainTex("Albedo", 2D) = "white" {} 13 14 _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5 15 16 _BumpScale("Noramal Scale", Range(0,1)) = 1.0 17 _BumpMap("Normal Map", 2D) = "bump" {} 18 19 [Enum(UV0,0,UV1,1)] _UVSec("UV Set for secondary textures", Float) = 0 20 21 [Space(20)] 22 _FabricScatterColor("Fabric Scatter Color", Color) = (1,1,1,1) 23 _FabricScatterScale("Fabric Scatter Scale", Range(0, 1)) = 0 24 25 [Space(20)] 26 _LayerTex("Layer", 2D) = "white" {} 27 _FurLength("Fur Length", Range(.0002, 10)) = .25 28 _Cutoff("Alpha Cutoff", Range(0,1)) = 0.5 // how "thick" 29 _CutoffEnd("Alpha Cutoff end", Range(0,1)) = 0.5 // how thick they are at the end 30 _EdgeFade("Edge Fade", Range(0,1)) = 0.4 31 _Gravity("Gravity Direction", Vector) = (0,-1,0,0) 32 _GravityStrength("Gravity Strength", Range(0,1)) = 0.25 33 _FlowMap("Flow Map", 2D) = "gray"{} 34 _UVOffset("UVOffset",Range(0,1))=0 35 [Header(Shadow)] 36 _ShadowColor("Shadow Color", Color) = (0,0,0,0) 37 _ShadowLerp("Shadow AO",Range(0,1)) = 1 38 // Blending state 39 [Header(Settings)] 40 _Mode("__mode", Float) = 0.0 41 [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend Mode", Float) = 5 42 [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend ("Dst Blend Mode", Float) = 10 43 [Toggle]_ZWrite("__zw", Float) = 1.0 44 [Toggle(_ALPHATEST_ON)]_ALPHATEST_ON("_ALPHATEST_ON",Float) =1 45 } 46 SubShader 47 { 48 Tags { "RenderType"="Opaque" "PerformanceChecks" = "False"} 49 50 LOD 100 51 HLSLINCLUDE 52 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 53 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" 54 #define UNITY_SETUP_BRDF_INPUT MetallicSetup 55 #define _NORMALMAP_URP 1 56 #define _FABRIC_URP 1 57 #define _FUR_URP 1 58 59 sampler2D _LayerTex; 60 sampler2D _BumpMap; 61 sampler2D _FlowMap; 62 sampler2D _MainTex; 63 sampler2D _OcclusionMap; 64 65 CBUFFER_START(UnityPerMaterial) 66 half _UVOffset; 67 half3 _FabricScatterColor; 68 half _FabricScatterScale; 69 float4 _MainTex_ST; 70 float4 _LayerTex_ST; 71 half _Glossiness; 72 half _FurLength; 73 half _GravityStrength; 74 half4 _Color; 75 half3 _Gravity; 76 half _CutoffEnd; 77 half _EdgeFade; 78 half _OcclusionStrength; 79 half _Cutoff; 80 half _BumpScale; 81 float _Metallic; 82 83 // //PBR 84 float3 _Albedo; 85 86 float3 _Specular; 87 float _Smoothness; 88 float _Occlusion; 89 float3 _Emission; 90 float _Alpha; 91 float4 _ShadowColor; 92 half _ShadowLerp; 93 CBUFFER_END 94 half _FUR_OFFSET; 95 96 // 97 ENDHLSL 98 99 Pass 100 { 101 Name "FurRender" 102 Tags{ "LightMode" = "FurRendererBase"} 103 //Blend[_SrcBlend][_DstBlend] 104 ZWrite[_ZWrite] 105 HLSLPROGRAM 106 // make fog work 107 #pragma multi_compile_fog 108 #pragma shader_feature _ _TANGENT_TO_WORLD 109 //#pragma shader_feature _ _PARALLAXMAP 110 #pragma shader_feature _ _GI_ON 111 #pragma multi_compile _ LIGHTMAP_ON 112 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS 113 #pragma shader_feature _NORMALMAP 114 #pragma shader_feature _ _RECEIVE_SHADOWS 115 //#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 116 #pragma shader_feature _EMISSION 117 #pragma shader_feature _METALLICGLOSSMAP 118 #pragma shader_feature ___ _DETAIL_MULX2 119 #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 120 #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 121 #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF 122 #pragma shader_feature _NORMALMAP_URP_ON _NORMALMAP_URP_OFF 123 // #define SHADER_TARGET 100 124 125 #pragma vertex vert_LayerBase 126 #pragma fragment frag_LayerBase 127 128 #include "FurCoreData.hlsl" 129 130 ENDHLSL 131 } 132 Pass 133 { 134 Name "FurRender" 135 Tags{ "LightMode" = "FurRendererLayer"} 136 Blend[_SrcBlend][_DstBlend] 137 ZWrite[_ZWrite] 138 HLSLPROGRAM 139 // make fog work 140 #pragma multi_compile_fog 141 #pragma shader_feature _ _TANGENT_TO_WORLD 142 //#pragma shader_feature _ _PARALLAXMAP 143 #pragma shader_feature _ _GI_ON 144 #pragma multi_compile _ LIGHTMAP_ON 145 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS 146 #pragma shader_feature _NORMALMAP 147 #pragma shader_feature _ _RECEIVE_SHADOWS 148 //#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 149 #pragma shader_feature _EMISSION 150 #pragma shader_feature _METALLICGLOSSMAP 151 #pragma shader_feature ___ _DETAIL_MULX2 152 #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 153 #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF 154 #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF 155 #pragma shader_feature _NORMALMAP_URP_ON _NORMALMAP_URP_OFF 156 157 #pragma vertex vert_LayerBase 158 #pragma fragment frag_LayerBase 159 160 #include "FurCoreData.hlsl" 161 162 ENDHLSL 163 } 164 Pass 165 { 166 167 Name "ShadowCaster" 168 Tags { "LightMode"="ShadowCaster" } 169 170 ZWrite On 171 ZTest LEqual 172 173 HLSLPROGRAM 174 #define ASE_SRP_VERSION 70301 175 176 #pragma prefer_hlslcc gles 177 #pragma exclude_renderers d3d11_9x 178 179 #pragma vertex vert 180 #pragma fragment frag 181 182 #define SHADERPASS_SHADOWCASTER 183 184 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 185 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" 186 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl" 187 #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" 188 189 190 191 struct VertexInput 192 { 193 float4 vertex : POSITION; 194 float3 ase_normal : NORMAL; 195 196 UNITY_VERTEX_INPUT_INSTANCE_ID 197 }; 198 199 struct VertexOutput 200 { 201 float4 clipPos : SV_POSITION; 202 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION) 203 float3 worldPos : TEXCOORD0; 204 #endif 205 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) && defined(ASE_NEEDS_FRAG_SHADOWCOORDS) 206 float4 shadowCoord : TEXCOORD1; 207 #endif 208 209 UNITY_VERTEX_INPUT_INSTANCE_ID 210 UNITY_VERTEX_OUTPUT_STEREO 211 }; 212 213 CBUFFER_START(UnityPerMaterial) 214 #ifdef _TRANSMISSION_ASE 215 float _TransmissionShadow; 216 #endif 217 #ifdef _TRANSLUCENCY_ASE 218 float _TransStrength; 219 float _TransNormal; 220 float _TransScattering; 221 float _TransDirect; 222 float _TransAmbient; 223 float _TransShadow; 224 #endif 225 #ifdef TESSELLATION_ON 226 float _TessPhongStrength; 227 float _TessValue; 228 float _TessMin; 229 float _TessMax; 230 float _TessEdgeLength; 231 float _TessMaxDisp; 232 #endif 233 CBUFFER_END 234 235 236 237 float3 _LightDirection; 238 239 VertexOutput VertexFunction( VertexInput v ) 240 { 241 VertexOutput o; 242 UNITY_SETUP_INSTANCE_ID(v); 243 UNITY_TRANSFER_INSTANCE_ID(v, o); 244 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO( o ); 245 246 247 #ifdef ASE_ABSOLUTE_VERTEX_POS 248 float3 defaultVertexValue = v.vertex.xyz; 249 #else 250 float3 defaultVertexValue = float3(0, 0, 0); 251 #endif 252 float3 vertexValue = defaultVertexValue; 253 #ifdef ASE_ABSOLUTE_VERTEX_POS 254 v.vertex.xyz = vertexValue; 255 #else 256 v.vertex.xyz += vertexValue; 257 #endif 258 259 v.ase_normal = v.ase_normal; 260 261 float3 positionWS = TransformObjectToWorld( v.vertex.xyz ); 262 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION) 263 o.worldPos = positionWS; 264 #endif 265 float3 normalWS = TransformObjectToWorldDir(v.ase_normal); 266 267 float4 clipPos = TransformWorldToHClip( ApplyShadowBias( positionWS, normalWS, _LightDirection ) ); 268 269 #if UNITY_REVERSED_Z 270 clipPos.z = min(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE); 271 #else 272 clipPos.z = max(clipPos.z, clipPos.w * UNITY_NEAR_CLIP_VALUE); 273 #endif 274 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) && defined(ASE_NEEDS_FRAG_SHADOWCOORDS) 275 VertexPositionInputs vertexInput = (VertexPositionInputs)0; 276 vertexInput.positionWS = positionWS; 277 vertexInput.positionCS = clipPos; 278 o.shadowCoord = GetShadowCoord( vertexInput ); 279 #endif 280 o.clipPos = clipPos; 281 return o; 282 } 283 284 #if defined(TESSELLATION_ON) 285 struct VertexControl 286 { 287 float4 vertex : INTERNALTESSPOS; 288 float3 ase_normal : NORMAL; 289 290 UNITY_VERTEX_INPUT_INSTANCE_ID 291 }; 292 293 struct TessellationFactors 294 { 295 float edge[3] : SV_TessFactor; 296 float inside : SV_InsideTessFactor; 297 }; 298 299 VertexControl vert ( VertexInput v ) 300 { 301 VertexControl o; 302 UNITY_SETUP_INSTANCE_ID(v); 303 UNITY_TRANSFER_INSTANCE_ID(v, o); 304 o.vertex = v.vertex; 305 o.ase_normal = v.ase_normal; 306 307 return o; 308 } 309 310 TessellationFactors TessellationFunction (InputPatch<VertexControl,3> v) 311 { 312 TessellationFactors o; 313 float4 tf = 1; 314 float tessValue = _TessValue; float tessMin = _TessMin; float tessMax = _TessMax; 315 float edgeLength = _TessEdgeLength; float tessMaxDisp = _TessMaxDisp; 316 #if defined(ASE_FIXED_TESSELLATION) 317 tf = FixedTess( tessValue ); 318 #elif defined(ASE_DISTANCE_TESSELLATION) 319 tf = DistanceBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, tessValue, tessMin, tessMax, GetObjectToWorldMatrix(), _WorldSpaceCameraPos ); 320 #elif defined(ASE_LENGTH_TESSELLATION) 321 tf = EdgeLengthBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, GetObjectToWorldMatrix(), _WorldSpaceCameraPos, _ScreenParams ); 322 #elif defined(ASE_LENGTH_CULL_TESSELLATION) 323 tf = EdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, tessMaxDisp, GetObjectToWorldMatrix(), _WorldSpaceCameraPos, _ScreenParams, unity_CameraWorldClipPlanes ); 324 #endif 325 o.edge[0] = tf.x; o.edge[1] = tf.y; o.edge[2] = tf.z; o.inside = tf.w; 326 return o; 327 } 328 329 [domain("tri")] 330 [partitioning("fractional_odd")] 331 [outputtopology("triangle_cw")] 332 [patchconstantfunc("TessellationFunction")] 333 [outputcontrolpoints(3)] 334 VertexControl HullFunction(InputPatch<VertexControl, 3> patch, uint id : SV_OutputControlPointID) 335 { 336 return patch[id]; 337 } 338 339 [domain("tri")] 340 VertexOutput DomainFunction(TessellationFactors factors, OutputPatch<VertexControl, 3> patch, float3 bary : SV_DomainLocation) 341 { 342 VertexInput o = (VertexInput) 0; 343 o.vertex = patch[0].vertex * bary.x + patch[1].vertex * bary.y + patch[2].vertex * bary.z; 344 o.ase_normal = patch[0].ase_normal * bary.x + patch[1].ase_normal * bary.y + patch[2].ase_normal * bary.z; 345 346 #if defined(ASE_PHONG_TESSELLATION) 347 float3 pp[3]; 348 for (int i = 0; i < 3; ++i) 349 pp[i] = o.vertex.xyz - patch[i].ase_normal * (dot(o.vertex.xyz, patch[i].ase_normal) - dot(patch[i].vertex.xyz, patch[i].ase_normal)); 350 float phongStrength = _TessPhongStrength; 351 o.vertex.xyz = phongStrength * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-phongStrength) * o.vertex.xyz; 352 #endif 353 UNITY_TRANSFER_INSTANCE_ID(patch[0], o); 354 return VertexFunction(o); 355 } 356 #else 357 VertexOutput vert ( VertexInput v ) 358 { 359 return VertexFunction( v ); 360 } 361 #endif 362 363 half4 frag(VertexOutput IN ) : SV_TARGET 364 { 365 UNITY_SETUP_INSTANCE_ID( IN ); 366 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( IN ); 367 368 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION) 369 float3 WorldPosition = IN.worldPos; 370 #endif 371 float4 ShadowCoords = float4( 0, 0, 0, 0 ); 372 373 #if defined(ASE_NEEDS_FRAG_SHADOWCOORDS) 374 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) 375 ShadowCoords = IN.shadowCoord; 376 #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS) 377 ShadowCoords = TransformWorldToShadowCoord( WorldPosition ); 378 #endif 379 #endif 380 381 382 float Alpha = 1; 383 float AlphaClipThreshold = 0.5; 384 385 #ifdef _ALPHATEST_ON 386 clip(Alpha - AlphaClipThreshold); 387 #endif 388 389 #ifdef LOD_FADE_CROSSFADE 390 LODDitheringTransition( IN.clipPos.xyz, unity_LODFade.x ); 391 #endif 392 return 0; 393 } 394 395 ENDHLSL 396 } 397 Pass 398 { 399 400 Name "DepthOnly" 401 Tags { "LightMode"="DepthOnly" } 402 403 ZWrite On 404 ColorMask 0 405 406 HLSLPROGRAM 407 #define ASE_SRP_VERSION 70301 408 409 #pragma prefer_hlslcc gles 410 #pragma exclude_renderers d3d11_9x 411 412 #pragma vertex vert 413 #pragma fragment frag 414 415 #define SHADERPASS_DEPTHONLY 416 417 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 418 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" 419 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl" 420 #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" 421 422 423 424 struct VertexInput 425 { 426 float4 vertex : POSITION; 427 float3 ase_normal : NORMAL; 428 429 UNITY_VERTEX_INPUT_INSTANCE_ID 430 }; 431 432 struct VertexOutput 433 { 434 float4 clipPos : SV_POSITION; 435 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION) 436 float3 worldPos : TEXCOORD0; 437 #endif 438 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) && defined(ASE_NEEDS_FRAG_SHADOWCOORDS) 439 float4 shadowCoord : TEXCOORD1; 440 #endif 441 442 UNITY_VERTEX_INPUT_INSTANCE_ID 443 UNITY_VERTEX_OUTPUT_STEREO 444 }; 445 446 CBUFFER_START(UnityPerMaterial) 447 #ifdef _TRANSMISSION_ASE 448 float _TransmissionShadow; 449 #endif 450 #ifdef _TRANSLUCENCY_ASE 451 float _TransStrength; 452 float _TransNormal; 453 float _TransScattering; 454 float _TransDirect; 455 float _TransAmbient; 456 float _TransShadow; 457 #endif 458 #ifdef TESSELLATION_ON 459 float _TessPhongStrength; 460 float _TessValue; 461 float _TessMin; 462 float _TessMax; 463 float _TessEdgeLength; 464 float _TessMaxDisp; 465 #endif 466 CBUFFER_END 467 468 469 470 VertexOutput VertexFunction( VertexInput v ) 471 { 472 VertexOutput o = (VertexOutput)0; 473 UNITY_SETUP_INSTANCE_ID(v); 474 UNITY_TRANSFER_INSTANCE_ID(v, o); 475 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); 476 477 478 #ifdef ASE_ABSOLUTE_VERTEX_POS 479 float3 defaultVertexValue = v.vertex.xyz; 480 #else 481 float3 defaultVertexValue = float3(0, 0, 0); 482 #endif 483 float3 vertexValue = defaultVertexValue; 484 #ifdef ASE_ABSOLUTE_VERTEX_POS 485 v.vertex.xyz = vertexValue; 486 #else 487 v.vertex.xyz += vertexValue; 488 #endif 489 490 v.ase_normal = v.ase_normal; 491 float3 positionWS = TransformObjectToWorld( v.vertex.xyz ); 492 float4 positionCS = TransformWorldToHClip( positionWS ); 493 494 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION) 495 o.worldPos = positionWS; 496 #endif 497 498 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) && defined(ASE_NEEDS_FRAG_SHADOWCOORDS) 499 VertexPositionInputs vertexInput = (VertexPositionInputs)0; 500 vertexInput.positionWS = positionWS; 501 vertexInput.positionCS = positionCS; 502 o.shadowCoord = GetShadowCoord( vertexInput ); 503 #endif 504 o.clipPos = positionCS; 505 return o; 506 } 507 508 #if defined(TESSELLATION_ON) 509 struct VertexControl 510 { 511 float4 vertex : INTERNALTESSPOS; 512 float3 ase_normal : NORMAL; 513 514 UNITY_VERTEX_INPUT_INSTANCE_ID 515 }; 516 517 struct TessellationFactors 518 { 519 float edge[3] : SV_TessFactor; 520 float inside : SV_InsideTessFactor; 521 }; 522 523 VertexControl vert ( VertexInput v ) 524 { 525 VertexControl o; 526 UNITY_SETUP_INSTANCE_ID(v); 527 UNITY_TRANSFER_INSTANCE_ID(v, o); 528 o.vertex = v.vertex; 529 o.ase_normal = v.ase_normal; 530 531 return o; 532 } 533 534 TessellationFactors TessellationFunction (InputPatch<VertexControl,3> v) 535 { 536 TessellationFactors o; 537 float4 tf = 1; 538 float tessValue = _TessValue; float tessMin = _TessMin; float tessMax = _TessMax; 539 float edgeLength = _TessEdgeLength; float tessMaxDisp = _TessMaxDisp; 540 #if defined(ASE_FIXED_TESSELLATION) 541 tf = FixedTess( tessValue ); 542 #elif defined(ASE_DISTANCE_TESSELLATION) 543 tf = DistanceBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, tessValue, tessMin, tessMax, GetObjectToWorldMatrix(), _WorldSpaceCameraPos ); 544 #elif defined(ASE_LENGTH_TESSELLATION) 545 tf = EdgeLengthBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, GetObjectToWorldMatrix(), _WorldSpaceCameraPos, _ScreenParams ); 546 #elif defined(ASE_LENGTH_CULL_TESSELLATION) 547 tf = EdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, tessMaxDisp, GetObjectToWorldMatrix(), _WorldSpaceCameraPos, _ScreenParams, unity_CameraWorldClipPlanes ); 548 #endif 549 o.edge[0] = tf.x; o.edge[1] = tf.y; o.edge[2] = tf.z; o.inside = tf.w; 550 return o; 551 } 552 553 [domain("tri")] 554 [partitioning("fractional_odd")] 555 [outputtopology("triangle_cw")] 556 [patchconstantfunc("TessellationFunction")] 557 [outputcontrolpoints(3)] 558 VertexControl HullFunction(InputPatch<VertexControl, 3> patch, uint id : SV_OutputControlPointID) 559 { 560 return patch[id]; 561 } 562 563 [domain("tri")] 564 VertexOutput DomainFunction(TessellationFactors factors, OutputPatch<VertexControl, 3> patch, float3 bary : SV_DomainLocation) 565 { 566 VertexInput o = (VertexInput) 0; 567 o.vertex = patch[0].vertex * bary.x + patch[1].vertex * bary.y + patch[2].vertex * bary.z; 568 o.ase_normal = patch[0].ase_normal * bary.x + patch[1].ase_normal * bary.y + patch[2].ase_normal * bary.z; 569 570 #if defined(ASE_PHONG_TESSELLATION) 571 float3 pp[3]; 572 for (int i = 0; i < 3; ++i) 573 pp[i] = o.vertex.xyz - patch[i].ase_normal * (dot(o.vertex.xyz, patch[i].ase_normal) - dot(patch[i].vertex.xyz, patch[i].ase_normal)); 574 float phongStrength = _TessPhongStrength; 575 o.vertex.xyz = phongStrength * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-phongStrength) * o.vertex.xyz; 576 #endif 577 UNITY_TRANSFER_INSTANCE_ID(patch[0], o); 578 return VertexFunction(o); 579 } 580 #else 581 VertexOutput vert ( VertexInput v ) 582 { 583 return VertexFunction( v ); 584 } 585 #endif 586 587 half4 frag(VertexOutput IN ) : SV_TARGET 588 { 589 UNITY_SETUP_INSTANCE_ID(IN); 590 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( IN ); 591 592 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION) 593 float3 WorldPosition = IN.worldPos; 594 #endif 595 float4 ShadowCoords = float4( 0, 0, 0, 0 ); 596 597 #if defined(ASE_NEEDS_FRAG_SHADOWCOORDS) 598 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) 599 ShadowCoords = IN.shadowCoord; 600 #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS) 601 ShadowCoords = TransformWorldToShadowCoord( WorldPosition ); 602 #endif 603 #endif 604 605 606 float Alpha = 1; 607 float AlphaClipThreshold = 0.5; 608 609 #ifdef _ALPHATEST_ON 610 clip(Alpha - AlphaClipThreshold); 611 #endif 612 613 #ifdef LOD_FADE_CROSSFADE 614 LODDitheringTransition( IN.clipPos.xyz, unity_LODFade.x ); 615 #endif 616 return 0; 617 } 618 ENDHLSL 619 } 620 } 621 }
1 struct Attributes 2 { 3 float4 positionOS: POSITION; 4 float2 uv : TEXCOORD0; 5 half2 lightmapUV : TEXCOORD1; 6 float4 tangent : TANGENT; 7 float3 normal : NORMAL; 8 }; 9 10 struct Varyings 11 { 12 float4 positionHCS : SV_POSITION; 13 float4 uv : TEXCOORD0; 14 float3 posWS : TEXCOORD1; 15 float3 eyeVec : TEXCOORD2; 16 float4 tangentToWorldAndPackedData[3]: TEXCOORD3; 17 half4 ambientOrLightmapUV : TEXCOORD6; 18 float3 normalWS : TEXCOORD7; 19 float4 shadowCoord : TEXCOORD8; 20 float4 lightmapUVOrVertexSH : TEXCOORD9; 21 float3 viewWS : TEXCOORD10; 22 half4 fogFactorAndVertexLight : TEXCOORD11; 23 float4 screenPos : TEXCOORD12; 24 //TODO 25 // UNITY_SHADOW_COORDS(6) 26 // UNITY_FOG_COORDS(7) 27 // #else 28 // UNITY_LIGHTING_COORDS(6,7) 29 // UNITY_FOG_COORDS(8) 30 }; 31 32 33 34 #include "UtilsInclude.hlsl" 35 // #define DIRLIGHTMAP_COMBINED 36 37 38 Varyings vert (Attributes IN, half FUR_OFFSET =0) 39 { 40 UNITY_SETUP_INSTANCE_ID(IN); 41 Varyings OUT; 42 OUT = (Varyings)0; 43 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); 44 45 //Transform vertexPos by normal 46 //短絨毛 47 half3 direction = lerp(IN.normal, _Gravity * _GravityStrength + IN.normal * (1 - _GravityStrength), _FUR_OFFSET); 48 //長毛 49 // half3 direction = lerp(IN.normal, _Gravity * _GravityStrength + IN.normal, _FUR_OFFSET); 50 IN.positionOS.xyz += direction * _FurLength * _FUR_OFFSET; 51 OUT.posWS = TransformObjectToWorld(IN.positionOS.xyz); 52 float3 positionWS = TransformObjectToWorld( IN.positionOS.xyz ); 53 float4 positionCS = TransformWorldToHClip( positionWS ); 54 OUT.screenPos = ComputeScreenPos(positionCS); 55 56 OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz); 57 OUT.uv.xy = TRANSFORM_TEX(IN.uv, _MainTex); 58 OUT.viewWS = normalize( _WorldSpaceCameraPos - OUT.posWS); 59 VertexNormalInputs normalInput = GetVertexNormalInputs( IN.normal, IN.tangent ); 60 half3 vertexLight = VertexLighting( positionWS, normalInput.normalWS ); 61 half fogFactor = ComputeFogFactor( positionCS.z ); 62 OUT.fogFactorAndVertexLight = half4(fogFactor, vertexLight); 63 OUT.eyeVec = NormalizePerVertexNormal(OUT.posWS.xyz - _WorldSpaceCameraPos); 64 half3 normalWS = TransformObjectToWorldNormal(IN.normal); 65 OUT.normalWS = normalWS; 66 #ifdef _TANGENT_TO_WORLD 67 float4 tangentWorld = float4(TransformObjectToWorldDir(IN.tangent.xyz), IN.tangent.w); 68 float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWS, tangentWorld.xyz, tangentWorld.w); 69 OUT.tangentToWorldAndPackedData[0].xyz = tangentToWorld[0]; 70 OUT.tangentToWorldAndPackedData[1].xyz = tangentToWorld[1]; 71 OUT.tangentToWorldAndPackedData[2].xyz = tangentToWorld[2]; 72 #else 73 OUT.tangentToWorldAndPackedData[0].xyz = 0; 74 OUT.tangentToWorldAndPackedData[1].xyz = 0; 75 OUT.tangentToWorldAndPackedData[2].xyz = normalWS; 76 #endif 77 78 #ifdef _PARALLAXMAP 79 TANGENT_SPACE_ROTATION; 80 half3 viewDirForParallax = mul (rotation, ObjSpaceViewDir(IN.positionOS)); 81 OUT.tangentToWorldAndPackedData[0].w = viewDirForParallax.x; 82 OUT.tangentToWorldAndPackedData[1].w = viewDirForParallax.y; 83 OUT.tangentToWorldAndPackedData[2].w = viewDirForParallax.z; 84 #endif 85 86 VertexPositionInputs vertexInput = (VertexPositionInputs)0; 87 vertexInput.positionWS = positionWS; 88 vertexInput.positionCS = positionCS; 89 OUTPUT_LIGHTMAP_UV(IN.lightmapUV, unity_LightmapST, OUT.lightmapUVOrVertexSH.xy); 90 OUTPUT_SH(normalWS, OUT.lightmapUVOrVertexSH.xyz); 91 92 OUT.ambientOrLightmapUV = VertexGIForward(IN, OUT.posWS, normalWS); 93 //TODO Fog 94 //TODO Shadow 95 OUT.shadowCoord = GetShadowCoord( vertexInput ); 96 OUT.shadowCoord = TransformWorldToShadowCoord(positionWS); 97 98 return OUT; 99 } 100 101 half4 frag (Varyings IN, half FUR_OFFSET = 0) : SV_Target 102 { 103 //Data 104 float3 Albedo = float3(0.5, 0.5, 0.5); 105 float Metallic = 0; 106 float3 Specular = 0.5; 107 float Smoothness = 0.5; 108 float Occlusion = 1; 109 float3 Emission = 0; 110 float Alpha = 1; 111 float3 BakedGI = 0; 112 113 InputData inputData; 114 inputData.positionWS = IN.posWS; 115 inputData.viewDirectionWS = IN.viewWS; 116 inputData.shadowCoord = IN.shadowCoord; 117 inputData.vertexLighting = IN.fogFactorAndVertexLight.yzw; 118 inputData.normalWS = IN.normalWS; 119 inputData.fogCoord = IN.fogFactorAndVertexLight.x; 120 inputData.bakedGI = 0; 121 #ifdef _GI_ON 122 inputData.bakedGI = SAMPLE_GI( IN.lightmapUVOrVertexSH.xy, IN.lightmapUVOrVertexSH.xyz, IN.normalWS ); 123 #endif 124 125 half4 color = UniversalFragmentPBR( 126 inputData, 127 _Albedo, 128 _Metallic, 129 _Specular, 130 _Smoothness, 131 _Occlusion, 132 _Emission, 133 _Alpha); 134 135 #ifdef _REFRACTION_ASE 136 float4 projScreenPos = ScreenPos / ScreenPos.w; 137 float3 refractionOffset = ( RefractionIndex - 1.0 ) * mul( UNITY_MATRIX_V, WorldNormal ).xyz * ( 1.0 - dot( WorldNormal, WorldViewDirection ) ); 138 projScreenPos.xy += refractionOffset.xy; 139 float3 refraction = SHADERGRAPH_SAMPLE_SCENE_COLOR( projScreenPos ) * RefractionColor; 140 color.rgb = lerp( refraction, color.rgb, color.a ); 141 color.a = 1; 142 #endif 143 144 #ifdef ASE_FOG 145 #ifdef TERRAIN_SPLAT_ADDPASS 146 color.rgb = MixFogColor(color.rgb, half3( 0, 0, 0 ), IN.fogFactorAndVertexLight.x ); 147 #else 148 color.rgb = MixFog(color.rgb, IN.fogFactorAndVertexLight.x); 149 #endif 150 #endif 151 152 // 153 //Dither 154 //UnityApplyDitherCrossFade(IN.positionHCS.xy); 155 half facing = dot(-IN.eyeVec, IN.tangentToWorldAndPackedData[2].xyz); 156 facing = saturate(ceil(facing)) * 2 - 1; 157 158 FRAGMENT_SETUP(s) 159 UNITY_SETUP_INSTANCE_ID(IN); 160 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN); 161 162 Light mainLight = GetMainLight (IN.shadowCoord); 163 half occlusion = CalOcclusion(IN.uv.xy); 164 165 // #ifdef _GI_ON 166 // inputData.bakedGI = SAMPLE_GI(IN.lightmapUVOrVertexSH.xy, IN.lightmapUVOrVertexSH.xyz, IN.normalWS); 167 // #endif 168 //PBR 169 BRDFData brdfData; 170 half3 albedo = 0.5; 171 half3 specular = .5; 172 half brdfAlpha = 1; 173 InitializeBRDFData(albedo,0,specular,0.5, brdfAlpha, brdfData); 174 #ifdef _RECEIVE_SHADOWS 175 half lightAttenuation = mainLight.distanceAttenuation * mainLight.shadowAttenuation; 176 #else 177 half lightAttenuation = 1; 178 #endif 179 half NdotL = saturate(dot(inputData.normalWS, mainLight.direction)); 180 half3 radiance = mainLight.color * (lightAttenuation * NdotL); 181 // half3 GIcolor = GlobalIllumination(brdfData, inputData.bakedGI, occlusion, inputData.normalWS, inputData.viewDirectionWS); 182 // half3 BRDFColor = LightingPhysicallyBased(brdfData, mainLight, inputData.normalWS, inputData.viewDirectionWS); 183 // 184 185 half4 c = FABRIC_BRDF_PBS(s.diffColor, s.specColor, s.oneMinusReflectivity, s.smoothness, s.normalWorld, -s.eyeVec, mainLight, inputData, lightAttenuation); 186 187 c.rgb += CalEmission(IN.uv.xy); 188 189 //UNITY_APPLY_FOG(i.fogCoord, c.rgb); 190 // half alpha = tex2D(_LayerTex, TRANSFORM_TEX(IN.uv.xy, _LayerTex)).r; 191 float2 uvoffset = tex2D(_FlowMap, IN.uv.xy).rg*2-1; 192 // return tex2D(_FlowMap, IN.uv); 193 half alpha = tex2D(_LayerTex, TRANSFORM_TEX(IN.uv.xy, _LayerTex) + _UVOffset * uvoffset * _FUR_OFFSET).r; 194 alpha = step(lerp(0, _CutoffEnd, _FUR_OFFSET), alpha); 195 c.a = 1 - _FUR_OFFSET * _FUR_OFFSET; 196 c.a += dot(-s.eyeVec, s.normalWorld) - _EdgeFade; 197 c.a = max(0, c.a); 198 c.a *= alpha; 199 c = half4(c.rgb * lerp(lerp(_ShadowColor.rgb, 1, _FUR_OFFSET), 1, _ShadowLerp), c.a); 200 // float3 mainAtten = mainLight.color * mainLight.distanceAttenuation; 201 // mainAtten = lerp( mainAtten, mainAtten * mainLight.shadowAttenuation, shadow ); 202 203 // return half4(GIcolor+BRDFColor,1); 204 // return half4(mainLight.color * mainLight.distanceAttenuation,1); 205 // #ifdef MAIN_LIGHT_CALCULATE_SHADOWS 206 // return 1; 207 // #else 208 // return 0; 209 210 // #endif 211 return c; 212 } 213 Varyings vert_LayerBase(Attributes IN) 214 { 215 return vert(IN, 0); 216 } 217 Varyings vert_Layer(Attributes IN) 218 { 219 return vert(IN, .1); 220 } 221 half4 frag_LayerBase(Varyings IN) : SV_Target 222 { 223 return frag(IN, .0); 224 } 225 half4 frag_Layer(Varyings IN) : SV_Target 226 { 227 return frag(IN, .1); 228 }
效果: