Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.74 KB | None | 0 0
  1. // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2.  
  3. Shader "Custom/Merged Shader" {
  4. Properties {
  5. _Color("Main Color", Color) = (0.5,0.5,0.5,1)
  6. _MainTex("Top Texture", 2D) = "white" {}
  7. _MainTexSide("Side/Bottom Texture", 2D) = "white" {}
  8. _Ramp("Toon Ramp (RGB)", 2D) = "gray" {}
  9. _Normal("Normal/Noise", 2D) = "bump" {}
  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. _RimPower("Rim Power", Range(-2,20)) = 1
  16. _RimColor("Rim Color Top", Color) = (0.5,0.5,0.5,1)
  17. _RimColor2("Rim Color Side/Bottom", Color) = (0.5,0.5,0.5,1)
  18.  
  19. _MeltY("Melt Y", Float) = 0.0
  20. _MeltDistance("Melt Distance", Float) = 1.0
  21. _MeltCurve("Melt Curve", Range(1.0,10.0)) = 2.0
  22.  
  23. _Tess("Tessellation Amount", Range( 1, 32 )) = 10
  24. }
  25. SubShader {
  26. Tags { "RenderType"="Opaque" }
  27. LOD 200
  28.  
  29. CGPROGRAM
  30.  
  31.  
  32. // add the tessellate function here
  33. #pragma surface surf ToonRamp fullforwardshadows vertex:disp addshadow tessellate:tessDistance nolightmap
  34.  
  35. // to use tessellation we must target shader model 4.6 and up
  36. #pragma target 4.6
  37.  
  38. // include Unity's tessellation code
  39. #include "Tessellation.cginc"
  40. //#pragma surface surf ToonRamp
  41. sampler2D _Ramp;
  42. #pragma lighting ToonRamp exclude_path:prepass
  43. inline half4 LightingToonRamp(SurfaceOutput s, half3 lightDir, half atten)
  44. {
  45. #ifndef USING_DIRECTIONAL_LIGHT
  46. lightDir = normalize(lightDir);
  47. #endif
  48.  
  49. half d = dot(s.Normal, lightDir)*0.5 + 0.5;
  50. half3 ramp = tex2D(_Ramp, float2(d,d)).rgb;
  51.  
  52. half4 c;
  53. c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * 2);
  54. c.a = 0;
  55. return c;
  56. }
  57. sampler2D _MainTex, _MainTexSide, _Normal;
  58. float4 _Color, _RimColor, _RimColor2;
  59. float _RimPower;
  60. float _TopSpread, _EdgeWidth;
  61. float _Scale, _SideScale, _NoiseScale;
  62.  
  63. struct Input {
  64. float2 uv_MainTex : TEXCOORD0;
  65. float3 worldPos; // world position built-in value
  66. float3 worldNormal; // world normal built-in value
  67. float3 viewDir;// view direction built-in value we're using for rimlight
  68. };
  69.  
  70. //half _Glossiness;
  71. //half _Metallic;
  72. //fixed4 _Color;
  73.  
  74. half _MeltY;
  75. half _MeltDistance;
  76. half _MeltCurve;
  77.  
  78. float _Tess;
  79.  
  80. struct appdata {
  81. float4 vertex : POSITION;
  82. float4 tangent : TANGENT;
  83. float3 normal : NORMAL;
  84. float2 texcoord : TEXCOORD0;
  85. };
  86.  
  87. // A modified version of Unity's UnityCalcDistanceTessFactor that only adds tess verts if the vertex is in the melt range
  88. float MeltCalcDistanceTessFactor (float4 vertex, float minDist, float maxDist, float tess)
  89. {
  90. float3 wpos = mul(unity_ObjectToWorld,vertex).xyz;
  91. float dist = distance (wpos, _WorldSpaceCameraPos);
  92. float f = clamp(1.0 - (dist - minDist) / (maxDist - minDist), 0.01, 1.0);
  93.  
  94. float melt = (( wpos.y - _MeltY ) / _MeltDistance);
  95. // calculate the melt for the world position
  96. // in our normal vert function we saturate this subtract it from 1 so verts near the ground are 1 and join the mesh at 0
  97. // we only care if the object is in the 'melt' range, so any value between 0 & 1, regardless of the sign.
  98. // will add a threshold too so verts near the edges are tessellated too
  99.  
  100. if( melt < -0.1 || melt > 1.1 )
  101. {
  102. f = 0.01; // set the value to the lower end of the clamp
  103. }
  104.  
  105. // move the tess multiply here for clarity
  106. return f * tess;
  107. }
  108.  
  109. // A modified version of Unity's UnityDistanceBasedTess to run our version of TessFactor
  110. // Distance based tessellation:
  111. // Tessellation level is "tess" before "minDist" from camera, and linearly decreases to 1
  112. // up to "maxDist" from camera.
  113. float4 MeltDistanceBasedTess (float4 v0, float4 v1, float4 v2, float minDist, float maxDist, float tess)
  114. {
  115. float3 f;
  116. f.x = MeltCalcDistanceTessFactor (v0,minDist,maxDist,tess);
  117. f.y = MeltCalcDistanceTessFactor (v1,minDist,maxDist,tess);
  118. f.z = MeltCalcDistanceTessFactor (v2,minDist,maxDist,tess);
  119.  
  120. return UnityCalcTriEdgeTessFactors (f);
  121. }
  122.  
  123. float4 tessDistance(appdata v0, appdata v1, appdata v2)
  124. {
  125. float minDist = 10.0;
  126. float maxDist = 25.0;
  127.  
  128. // this unity function scales how much tessellation based on how close the camera is
  129. // objects further away keep the same vert count as before
  130.  
  131. // the last parameter is the factor of tessellation, increasing it in the material inspector increases verts created
  132. return MeltDistanceBasedTess(v0.vertex, v1.vertex, v2.vertex, minDist, maxDist, _Tess);
  133. }
  134.  
  135. float4 getNewVertPosition( float4 objectSpacePosition, float3 objectSpaceNormal )
  136. {
  137. float4 worldSpacePosition = mul( unity_ObjectToWorld, objectSpacePosition );
  138. float4 worldSpaceNormal = mul( unity_ObjectToWorld, float4(objectSpaceNormal,0) );
  139.  
  140. float melt = ( worldSpacePosition.y - _MeltY ) / _MeltDistance;
  141.  
  142. melt = 1 - saturate( melt );
  143. melt = pow( melt, _MeltCurve );
  144.  
  145. worldSpacePosition.xz += worldSpaceNormal.xz * melt;
  146.  
  147. return mul( unity_WorldToObject, worldSpacePosition );
  148. }
  149.  
  150. void disp( inout appdata v )
  151. {
  152. float4 vertPosition = getNewVertPosition( v.vertex, v.normal );
  153.  
  154. float4 bitangent = float4( cross( v.normal, v.tangent ), 0 );
  155. float vertOffset = 0.01;
  156.  
  157. float4 v1 = getNewVertPosition( v.vertex + v.tangent * vertOffset, v.normal );
  158. float4 v2 = getNewVertPosition( v.vertex + bitangent * vertOffset, v.normal );
  159.  
  160. float4 newTangent = v1 - vertPosition;
  161. float4 newBitangent = v2 - vertPosition;
  162.  
  163. v.normal = cross( newTangent, newBitangent );
  164.  
  165. v.vertex = vertPosition;
  166. }
  167.  
  168. void surf (Input IN, inout SurfaceOutput o) {
  169. // clamp (saturate) and increase(pow) the worldnormal value to use as a blend between the projected textures
  170. float3 blendNormal = saturate(pow(IN.worldNormal * 1.4,4));
  171.  
  172. // normal noise triplanar for x, y, z sides
  173. float3 xn = tex2D(_Normal, IN.worldPos.zy * _NoiseScale);
  174. float3 yn = tex2D(_Normal, IN.worldPos.zx * _NoiseScale);
  175. float3 zn = tex2D(_Normal, IN.worldPos.xy * _NoiseScale);
  176.  
  177. // lerped together all sides for noise texture
  178. float3 noisetexture = zn;
  179. noisetexture = lerp(noisetexture, xn, blendNormal.x);
  180. noisetexture = lerp(noisetexture, yn, blendNormal.y);
  181.  
  182. // triplanar for top texture for x, y, z sides
  183. float3 xm = tex2D(_MainTex, IN.worldPos.zy * _Scale);
  184. float3 zm = tex2D(_MainTex, IN.worldPos.xy * _Scale);
  185. float3 ym = tex2D(_MainTex, IN.worldPos.zx * _Scale);
  186.  
  187. // lerped together all sides for top texture
  188. float3 toptexture = zm;
  189. toptexture = lerp(toptexture, xm, blendNormal.x);
  190. toptexture = lerp(toptexture, ym, blendNormal.y);
  191.  
  192. // triplanar for side and bottom texture, x,y,z sides
  193. float3 x = tex2D(_MainTexSide, IN.worldPos.zy * _SideScale);
  194. float3 y = tex2D(_MainTexSide, IN.worldPos.zx * _SideScale);
  195. float3 z = tex2D(_MainTexSide, IN.worldPos.xy * _SideScale);
  196.  
  197. // lerped together all sides for side bottom texture
  198. float3 sidetexture = z;
  199. sidetexture = lerp(sidetexture, x, blendNormal.x);
  200. sidetexture = lerp(sidetexture, y, blendNormal.y);
  201.  
  202. // rim light for fuzzy top texture
  203. half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal * noisetexture));
  204.  
  205. // rim light for side/bottom texture
  206. half rim2 = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));
  207.  
  208. // dot product of world normal and surface normal + noise
  209. float worldNormalDotNoise = dot(o.Normal + (noisetexture.y + (noisetexture * 0.5)), IN.worldNormal.y);
  210.  
  211. // if dot product is higher than the top spread slider, multiplied by triplanar mapped top texture
  212. // step is replacing an if statement to avoid branching :
  213. // if (worldNormalDotNoise > _TopSpread{ o.Albedo = toptexture}
  214. float3 topTextureResult = step(_TopSpread, worldNormalDotNoise) * toptexture;
  215.  
  216. // if dot product is lower than the top spread slider, multiplied by triplanar mapped side/bottom texture
  217. float3 sideTextureResult = step(worldNormalDotNoise, _TopSpread) * sidetexture;
  218.  
  219. // if dot product is in between the two, make the texture darker
  220. float3 topTextureEdgeResult = step(_TopSpread, worldNormalDotNoise) * step(worldNormalDotNoise, _TopSpread + _EdgeWidth) * -0.15;
  221.  
  222. // final albedo color
  223. o.Albedo = topTextureResult + sideTextureResult + topTextureEdgeResult;
  224. o.Albedo *= _Color;
  225. // adding the fuzzy rimlight(rim) on the top texture, and the harder rimlight (rim2) on the side/bottom texture
  226. o.Emission = step(_TopSpread, worldNormalDotNoise) * _RimColor.rgb * pow(rim, _RimPower) + step(worldNormalDotNoise, _TopSpread) * _RimColor2.rgb * pow(rim2, _RimPower);
  227. }
  228. ENDCG
  229. }
  230. FallBack "Diffuse"
  231. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement