Advertisement
Guest User

TriplanarNormal.shader

a guest
Mar 9th, 2018
2,672
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.17 KB | None | 0 0
  1. Shader "Toon/Lit Tri Planar Normal" {
  2. Properties{
  3. _Color("Main Color", Color) = (0.5,0.5,0.5,1)
  4. _MainTex("Top Texture", 2D) = "white" {}
  5. _NormalT("Top Normal", 2D) = "bump" {}
  6. _MainTexSide("Side/Bottom Texture", 2D) = "white" {}
  7. _Normal("Side/Bottom Normal", 2D) = "bump" {}
  8. _Ramp("Toon Ramp (RGB)", 2D) = "gray" {}
  9. _Noise("Noise", 2D) = "white" {}
  10. _Scale("Top Scale", Range(-2,2)) = 1
  11. _SideScale("Side Scale", Range(-2,2)) = 1
  12. _NoiseScale("Noise Scale", Range(-2,2)) = 1
  13. _TopSpread("TopSpread", Range(-2,2)) = 1
  14. _EdgeWidth("EdgeWidth", Range(0,0.5)) = 1
  15. _EdgeColor("Edge Color", Color) = (0.5,0.5,0.5,1)
  16. _RimPower("Rim Power", Range(-2,20)) = 1
  17. _RimColor("Rim Color Top", Color) = (0.5,0.5,0.5,1)
  18. _RimColor2("Rim Color Side/Bottom", Color) = (0.5,0.5,0.5,1)
  19. }
  20.  
  21. SubShader{
  22. Tags{ "RenderType" = "Opaque" }
  23. LOD 200
  24.  
  25. CGPROGRAM
  26. #pragma surface surf ToonRamp
  27.  
  28. sampler2D _Ramp;
  29.  
  30. // custom lighting function that uses a texture ramp based
  31. // on angle between light direction and normal
  32. #pragma lighting ToonRamp exclude_path:prepass
  33. inline half4 LightingToonRamp(SurfaceOutput s, half3 lightDir, half atten)
  34. {
  35. #ifndef USING_DIRECTIONAL_LIGHT
  36. lightDir = normalize(lightDir);
  37. #endif
  38.  
  39. half d = dot(s.Normal, lightDir)*0.5 + 0.5;
  40. half3 ramp = tex2D(_Ramp, float2(d,d)).rgb;
  41.  
  42. half4 c;
  43. c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);
  44. c.a = 0;
  45. return c;
  46. }
  47.  
  48.  
  49. sampler2D _MainTex, _MainTexSide, _Normal, _Noise, _NormalT;
  50. float4 _Color, _RimColor, _RimColor2, _EdgeColor;
  51. float _RimPower;
  52. float _TopSpread, _EdgeWidth;
  53. float _Scale, _SideScale, _NoiseScale;
  54.  
  55. struct Input {
  56. float2 uv_MainTex : TEXCOORD0;
  57. float3 worldPos; // world position built-in value
  58. float3 worldNormal; INTERNAL_DATA // world normal built-in value
  59. float3 viewDir;// view direction built-in value we're using for rimlight
  60. };
  61.  
  62. void surf(Input IN, inout SurfaceOutput o) {
  63.  
  64. // clamp (saturate) and increase(pow) the worldnormal value to use as a blend between the projected textures
  65. float3 worldNormalE = WorldNormalVector(IN, o.Normal);
  66. float3 blendNormal = saturate(pow(worldNormalE * 1.4,4));
  67.  
  68.  
  69. // normal noise triplanar for x, y, z sides
  70. float3 xn = tex2D(_Noise, IN.worldPos.zy * _NoiseScale);
  71. float3 yn = tex2D(_Noise, IN.worldPos.zx * _NoiseScale);
  72. float3 zn = tex2D(_Noise, IN.worldPos.xy * _NoiseScale);
  73.  
  74. // lerped together all sides for noise texture
  75. float3 noisetexture = zn;
  76. noisetexture = lerp(noisetexture, xn, blendNormal.x);
  77. noisetexture = lerp(noisetexture, yn, blendNormal.y);
  78.  
  79. // triplanar for top texture for x, y, z sides
  80. float3 xm = tex2D(_MainTex, IN.worldPos.zy * _Scale);
  81. float3 zm = tex2D(_MainTex, IN.worldPos.xy * _Scale);
  82. float3 ym = tex2D(_MainTex, IN.worldPos.zx * _Scale);
  83.  
  84. // lerped together all sides for top texture
  85. float3 toptexture = zm;
  86. toptexture = lerp(toptexture, xm, blendNormal.x);
  87. toptexture = lerp(toptexture, ym, blendNormal.y);
  88.  
  89. // triplanar for top normal for x, y, z sides
  90.  
  91. float3 xnnt = UnpackNormal(tex2D(_NormalT, IN.worldPos.zy * _Scale));
  92. float3 znnt = UnpackNormal(tex2D(_NormalT, IN.worldPos.xy * _Scale));
  93. float3 ynnt = UnpackNormal(tex2D(_NormalT, IN.worldPos.zx * _Scale));
  94.  
  95. // lerped together all sides for top normal
  96. float3 toptextureNormal = znnt;
  97. toptextureNormal = lerp(toptextureNormal, xnnt, blendNormal.x);
  98. toptextureNormal = lerp(toptextureNormal, ynnt, blendNormal.y);
  99.  
  100. // triplanar for side normal for x, y, z sides
  101. float3 xnn = UnpackNormal(tex2D(_Normal, IN.worldPos.zy * _SideScale));
  102. float3 znn = UnpackNormal(tex2D(_Normal, IN.worldPos.xy * _SideScale));
  103. float3 ynn = UnpackNormal(tex2D(_Normal, IN.worldPos.zx * _SideScale));
  104.  
  105. // lerped together all sides for side normal
  106. float3 sidetextureNormal = znn;
  107. sidetextureNormal = lerp(sidetextureNormal, xnn, blendNormal.x);
  108. sidetextureNormal = lerp(sidetextureNormal, ynn, blendNormal.y);
  109.  
  110.  
  111. // triplanar for side and bottom texture, x,y,z sides
  112. float3 x = tex2D(_MainTexSide, IN.worldPos.zy * _SideScale);
  113. float3 y = tex2D(_MainTexSide, IN.worldPos.zx * _SideScale);
  114. float3 z = tex2D(_MainTexSide, IN.worldPos.xy * _SideScale);
  115.  
  116. // lerped together all sides for side bottom texture
  117. float3 sidetexture = z;
  118. sidetexture = lerp(sidetexture, x, blendNormal.x);
  119. sidetexture = lerp(sidetexture, y, blendNormal.y);
  120.  
  121.  
  122.  
  123. // dot product of world normal and surface normal + noise
  124. float worldNormalDotNoise = dot(o.Normal + (noisetexture.y + (noisetexture * 0.5)), worldNormalE.y);
  125.  
  126. // if dot product is higher than the top spread slider, multiplied by triplanar mapped top texture
  127. // step is replacing an if statement to avoid branching :
  128. // if (worldNormalDotNoise > _TopSpread{ o.Albedo = toptexture}
  129. float3 topTextureResult = step(_TopSpread + _EdgeWidth, worldNormalDotNoise) * toptexture;
  130. float3 topNormalResult = step(_TopSpread, worldNormalDotNoise) * toptextureNormal;
  131.  
  132. // if dot product is lower than the top spread slider, multiplied by triplanar mapped side/bottom texture
  133. float3 sideTextureResult = step(worldNormalDotNoise, _TopSpread) * sidetexture;
  134. float3 sideNormalResult = step(worldNormalDotNoise, _TopSpread) * sidetextureNormal;
  135.  
  136. // if dot product is in between the two, make the texture darker
  137. float3 topTextureEdgeResult = (step(_TopSpread , worldNormalDotNoise) * step(worldNormalDotNoise, _TopSpread + _EdgeWidth)) * _EdgeColor;
  138.  
  139. // final normal
  140. o.Normal = topNormalResult + sideNormalResult;
  141. // final albedo color
  142. o.Albedo = topTextureResult + sideTextureResult + topTextureEdgeResult;
  143. o.Albedo *= _Color;
  144.  
  145. // adding the fuzzy rimlight(rim) on the top texture, and the harder rimlight (rim2) on the side/bottom texture
  146. // rim light for fuzzy top texture
  147. half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));
  148.  
  149. // rim light for side/bottom texture
  150. half rim2 = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));
  151. o.Emission = step(_TopSpread + _EdgeWidth, worldNormalDotNoise) * _RimColor.rgb * pow(rim, _RimPower) + step(worldNormalDotNoise, _TopSpread) * _RimColor2.rgb * pow(rim2, _RimPower);
  152.  
  153.  
  154. }
  155. ENDCG
  156.  
  157. }
  158.  
  159. Fallback "Diffuse"
  160. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement