SHARE
TWEET

Unity Speedtree VR Shader - Camera position aligned Leafs

a guest Feb 17th, 2019 158 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Unity Speedtree Shader for VR
  2. // Based on Kritoas shader ( https://forum.unity.com/threads/unity-tree-billboard-bug-with-oculus-unity-what-is-going-on.406006/page-2)
  3. // I added the missing part for the Billboard/CameraPos alignment.
  4. // Only tested the SM3.0 shaders in Unity 2018.2.12f1.
  5. // This shader won't work with GPU Instancer or Vegetation Studio out of the box. To do this you'll need to modify the built-in shader includes.
  6. // Have Fun... Pepe 2019
  7.  
  8. // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
  9.  
  10. Shader "Nature/SpeedTreePepe"
  11. {
  12.   Properties
  13.   {
  14.     _Color("Main Color", Color) = (1,1,1,1)
  15.     _HueVariation("Hue Variation", Color) = (1.0,0.5,0.0,0.1)
  16.     _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
  17.   _DetailTex("Detail", 2D) = "black" {}
  18.   _BumpMap("Normal Map", 2D) = "bump" {}
  19.   _Cutoff("Alpha Cutoff", Range(0,1)) = 0.333
  20.     [MaterialEnum(Off,0,Front,1,Back,2)] _Cull("Cull", Int) = 2
  21.     [MaterialEnum(None,0,Fastest,1,Fast,2,Better,3,Best,4,Palm,5)] _WindQuality("Wind Quality", Range(0,5)) = 0
  22.   }
  23.  
  24.   //---------------------------------------------------------------------------------------------------------------------------------
  25.   // SM 3.0
  26.   //---------------------------------------------------------------------------------------------------------------------------------
  27.  
  28.   // targeting SM3.0+
  29.   SubShader
  30.   {
  31.     Tags
  32.     {
  33.       "Queue" = "Geometry"
  34.       "IgnoreProjector" = "True"
  35.       "RenderType" = "Opaque"
  36.       "DisableBatching" = "LODFading"
  37.     }
  38.     LOD 400
  39.     Cull[_Cull]
  40.  
  41.     CGPROGRAM
  42.     #pragma surface surf Lambert vertex:SpeedTreeVertPepe nodirlightmap nodynlightmap noshadowmask
  43.     #pragma target 3.0
  44.     #pragma multi_compile  LOD_FADE_PERCENTAGE LOD_FADE_CROSSFADE
  45.     #pragma instancing_options assumeuniformscaling lodfade maxcount:50
  46.     #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  47.     #pragma shader_feature EFFECT_BUMP
  48.     #pragma shader_feature EFFECT_HUE_VARIATION
  49.     #define ENABLE_WIND
  50.     #include "SpeedTreeCommon.cginc"
  51.  
  52.     void OffsetSpeedTreeVertexPepe(inout SpeedTreeVB data, float lodValue)
  53.     {
  54.     float3 finalPosition = data.vertex.xyz;
  55.  
  56. #ifdef ENABLE_WIND
  57.     half windQuality = _WindQuality * _WindEnabled;
  58.  
  59.     float3 rotatedWindVector, rotatedBranchAnchor;
  60.     if (windQuality <= WIND_QUALITY_NONE)
  61.     {
  62.       rotatedWindVector = float3(0.0f, 0.0f, 0.0f);
  63.       rotatedBranchAnchor = float3(0.0f, 0.0f, 0.0f);
  64.     }
  65.     else
  66.     {
  67.       // compute rotated wind parameters
  68.       rotatedWindVector = normalize(mul(_ST_WindVector.xyz, (float3x3)unity_ObjectToWorld));
  69.       rotatedBranchAnchor = normalize(mul(_ST_WindBranchAnchor.xyz, (float3x3)unity_ObjectToWorld)) * _ST_WindBranchAnchor.w;
  70.     }
  71. #endif
  72.  
  73. #if defined(GEOM_TYPE_BRANCH) || defined(GEOM_TYPE_FROND)
  74.  
  75.     // smooth LOD
  76. #ifdef LOD_FADE_PERCENTAGE
  77.     finalPosition = lerp(finalPosition, data.texcoord1.xyz, lodValue);
  78. #endif
  79.  
  80.     // frond wind, if needed
  81. #if defined(ENABLE_WIND) && defined(GEOM_TYPE_FROND)
  82.     if (windQuality == WIND_QUALITY_PALM)
  83.       finalPosition = RippleFrond(finalPosition, data.normal, data.texcoord.x, data.texcoord.y, data.texcoord2.x, data.texcoord2.y, data.texcoord2.z);
  84. #endif
  85.  
  86. #elif defined(GEOM_TYPE_LEAF)
  87.  
  88.     // remove anchor position
  89.     finalPosition -= data.texcoord1.xyz;
  90.     float3 unmodifiedPos = finalPosition;
  91.  
  92.     bool isFacingLeaf = data.color.a == 0;
  93.     if (isFacingLeaf)
  94.     {
  95. #ifdef LOD_FADE_PERCENTAGE
  96.       finalPosition *= lerp(1.0, data.texcoord1.w, lodValue);
  97. #endif
  98.     //Pepe - modified part
  99.     float offsetLen = length(finalPosition);
  100.     //finalPosition = mul(finalPosition.xyz, (float3x3)UNITY_MATRIX_IT_MV); //old camera facing (orients to view matrix, bad!!)
  101.  
  102.     //In case you want axis aligned billboards uncomment the lines below
  103.     //We use a modified inverse view matrix to axis align the billboards
  104.     //float3x3 axisMatrix = (float3x3)UNITY_MATRIX_IT_MV;
  105.     //axisMatrix[0].xyz = mul((float3x3)unity_WorldToObject,float3(-1, 0, 0));
  106.     //axisMatrix[1].xyz = float3(0, 1, 0);
  107.     //finalPosition = mul(finalPosition.xyz, (float3x3)axisMatrix);
  108.  
  109.     //We need the viewVector to align the billboards to the cameraposition
  110.     float3 lookAtPoint = mul(unity_ObjectToWorld, float4(data.texcoord1.xyz, data.vertex.w)) ;
  111.     float3 viewVector = normalize(_WorldSpaceCameraPos.xyz - lookAtPoint);
  112.  
  113.     //Then we create a LookAt matrix
  114.     float3 up = float3(0, 1, 0);
  115.     float3 zaxis = viewVector;
  116.     float3 xaxis = normalize(cross(up, zaxis));
  117.     float3 yaxis = cross(zaxis, xaxis);
  118.     float3x3 lookatMatrix = {
  119.       xaxis.x,            yaxis.x,            zaxis.x,
  120.       xaxis.y,            yaxis.y,            zaxis.y,
  121.       xaxis.z,            yaxis.z,            zaxis.z
  122.     };
  123.     //...and apply the rotation!
  124.     finalPosition = mul(lookatMatrix, finalPosition);
  125.  
  126.     finalPosition = normalize(finalPosition) * offsetLen; // make sure the offset vector is still scaled
  127.     }
  128.     else
  129.     {
  130. #ifdef LOD_FADE_PERCENTAGE
  131.       float3 lodPosition = float3(data.texcoord1.w, data.texcoord3.x, data.texcoord3.y);
  132.       lerp(finalPosition, lodPosition, lodValue);
  133. #endif
  134.     }
  135.  
  136. #ifdef ENABLE_WIND
  137.     // leaf wind
  138.     if (windQuality > WIND_QUALITY_FASTEST && windQuality < WIND_QUALITY_PALM)
  139.     {
  140.       float leafWindTrigOffset = data.texcoord1.x + data.texcoord1.y;
  141.       finalPosition = LeafWind(windQuality == WIND_QUALITY_BEST, data.texcoord2.w > 0.0, finalPosition, data.normal, data.texcoord2.x, float3(0,0,0), data.texcoord2.y, data.texcoord2.z, leafWindTrigOffset, rotatedWindVector);
  142.     }
  143. #endif
  144.  
  145.     // move back out to anchor
  146.     finalPosition += data.texcoord1.xyz;
  147.  
  148. #endif
  149.  
  150. #ifdef ENABLE_WIND
  151.     float3 treePos = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
  152.  
  153. #ifndef GEOM_TYPE_MESH
  154.     if (windQuality >= WIND_QUALITY_BETTER)
  155.     {
  156.       // branch wind (applies to all 3D geometry)
  157.       finalPosition = BranchWind(windQuality == WIND_QUALITY_PALM, finalPosition, treePos, float4(data.texcoord.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor);
  158.     }
  159. #endif
  160.  
  161.     if (windQuality > WIND_QUALITY_NONE)
  162.     {
  163.       // global wind
  164.       finalPosition = GlobalWind(finalPosition, treePos, true, rotatedWindVector, _ST_WindGlobal.x);
  165.     }
  166. #endif
  167.  
  168.     data.vertex.xyz = finalPosition;
  169.   }
  170.  
  171.   void SpeedTreeVertPepe(inout SpeedTreeVB IN, out Input OUT)
  172.   {
  173.     UNITY_INITIALIZE_OUTPUT(Input, OUT);
  174.  
  175.     OUT.mainTexUV = IN.texcoord.xy;
  176.     OUT.color = _Color;
  177.     OUT.color.rgb *= IN.color.r; // ambient occlusion factor
  178.  
  179. #ifdef EFFECT_HUE_VARIATION
  180.     float hueVariationAmount = frac(unity_ObjectToWorld[0].w + unity_ObjectToWorld[1].w + unity_ObjectToWorld[2].w);
  181.     hueVariationAmount += frac(IN.vertex.x + IN.normal.y + IN.normal.x) * 0.5 - 0.3;
  182.     OUT.HueVariationAmount = saturate(hueVariationAmount * _HueVariation.a);
  183. #endif
  184.  
  185. #ifdef GEOM_TYPE_BRANCH_DETAIL
  186.     // The two types are always in different sub-range of the mesh so no interpolation (between detail and blend) problem.
  187.     OUT.Detail.xy = IN.texcoord2.xy;
  188.     if (IN.color.a == 0) // Blend
  189.       OUT.Detail.z = IN.texcoord2.z;
  190.     else // Detail texture
  191.       OUT.Detail.z = 2.5f; // stay out of Blend's .z range
  192. #endif
  193.  
  194.     OffsetSpeedTreeVertexPepe(IN, unity_LODFade.x);
  195.  
  196.     UNITY_TRANSFER_DITHER_CROSSFADE(OUT, IN.vertex)
  197.   }
  198.  
  199.   void surf(Input IN, inout SurfaceOutput OUT)
  200.   {
  201.     SpeedTreeFragOut o;
  202.     SpeedTreeFrag(IN, o);
  203.     SPEEDTREE_COPY_FRAG(OUT, o)
  204.   }
  205.   ENDCG
  206.  
  207.     //---------------------------------------------------------------------------------------------------------------------------------
  208.     // ShadowCaster Pass
  209.     //---------------------------------------------------------------------------------------------------------------------------------
  210.  
  211.   Pass
  212.   {
  213.     Tags{ "LightMode" = "ShadowCaster" }
  214.  
  215.     CGPROGRAM
  216.     #pragma vertex vert
  217.     #pragma fragment frag
  218.     #pragma target 3.0
  219.     #pragma multi_compile  LOD_FADE_PERCENTAGE LOD_FADE_CROSSFADE
  220.     #pragma multi_compile_instancing
  221.     #pragma instancing_options assumeuniformscaling lodfade maxcount:50
  222.     #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  223.     #pragma multi_compile_shadowcaster
  224.     #define ENABLE_WIND
  225.     #include "SpeedTreeCommon.cginc"
  226.  
  227.     void OffsetSpeedTreeVertexShadow(inout SpeedTreeVB data, float lodValue)
  228.     {
  229.     float3 finalPosition = data.vertex.xyz;
  230.  
  231. #ifdef ENABLE_WIND
  232.     half windQuality = _WindQuality * _WindEnabled;
  233.  
  234.     float3 rotatedWindVector, rotatedBranchAnchor;
  235.     if (windQuality <= WIND_QUALITY_NONE)
  236.     {
  237.       rotatedWindVector = float3(0.0f, 0.0f, 0.0f);
  238.       rotatedBranchAnchor = float3(0.0f, 0.0f, 0.0f);
  239.     }
  240.     else
  241.     {
  242.       //compute rotated wind parameters
  243.       rotatedWindVector   = normalize(mul(_ST_WindVector.xyz, (float3x3)unity_ObjectToWorld));
  244.       rotatedBranchAnchor = normalize(mul(_ST_WindBranchAnchor.xyz, (float3x3)unity_ObjectToWorld)) * _ST_WindBranchAnchor.w;
  245.     }
  246. #endif
  247.  
  248. #if defined(GEOM_TYPE_BRANCH) || defined(GEOM_TYPE_FROND)
  249.  
  250.     // smooth LOD
  251. #ifdef LOD_FADE_PERCENTAGE
  252.     finalPosition = lerp(finalPosition, data.texcoord1.xyz, lodValue);
  253. #endif
  254.  
  255.     // frond wind, if needed
  256. #if defined(ENABLE_WIND) && defined(GEOM_TYPE_FROND)
  257.     if (windQuality == WIND_QUALITY_PALM)
  258.       finalPosition = RippleFrond(finalPosition, data.normal, data.texcoord.x, data.texcoord.y, data.texcoord2.x, data.texcoord2.y, data.texcoord2.z);
  259. #endif
  260.  
  261. #elif defined(GEOM_TYPE_LEAF)
  262.  
  263.     // remove anchor position
  264.     finalPosition -= data.texcoord1.xyz;
  265.  
  266.     bool isFacingLeaf = data.color.a == 0;
  267.     if (isFacingLeaf)
  268.     {
  269. #ifdef LOD_FADE_PERCENTAGE
  270.       finalPosition *= lerp(1.0, data.texcoord1.w, lodValue);
  271. #endif
  272.       //Pepe: Shadowcaster Path - We don't apply Billboard transforms here
  273.       // face camera-facing leaf to camera
  274.       //float offsetLen = length(finalPosition);
  275.       //finalPosition = mul(finalPosition.xyz, (float3x3)UNITY_MATRIX_IT_MV); // inv(MV) * finalPosition    // old camera facing (orients to view matrix, bad!)
  276.       //finalPosition = normalize(finalPosition) * offsetLen; // make sure the offset vector is still scaled
  277.     }
  278.     else
  279.     {
  280. #ifdef LOD_FADE_PERCENTAGE
  281.       float3 lodPosition = float3(data.texcoord1.w, data.texcoord3.x, data.texcoord3.y);
  282.       finalPosition = lerp(finalPosition, lodPosition, lodValue);
  283. #endif
  284.     }
  285.  
  286. #ifdef ENABLE_WIND
  287.     // leaf wind
  288.     if (windQuality > WIND_QUALITY_FASTEST && windQuality < WIND_QUALITY_PALM)
  289.     {
  290.       float leafWindTrigOffset = data.texcoord1.x + data.texcoord1.y;
  291.       finalPosition = LeafWind(windQuality == WIND_QUALITY_BEST, data.texcoord2.w > 0.0, finalPosition, data.normal, data.texcoord2.x, float3(0,0,0), data.texcoord2.y, data.texcoord2.z, leafWindTrigOffset, rotatedWindVector);
  292.     }
  293. #endif
  294.  
  295.     // move back out to anchor
  296.     finalPosition += data.texcoord1.xyz;
  297.  
  298. #endif
  299.  
  300. #ifdef ENABLE_WIND
  301.     float3 treePos = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
  302.  
  303. #ifndef GEOM_TYPE_MESH
  304.     if (windQuality >= WIND_QUALITY_BETTER)
  305.     {
  306.       // branch wind (applies to all 3D geometry)
  307.       finalPosition = BranchWind(windQuality == WIND_QUALITY_PALM, finalPosition, treePos, float4(data.texcoord.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor);
  308.     }
  309. #endif
  310.  
  311.     if (windQuality > WIND_QUALITY_NONE)
  312.     {
  313.       // global wind
  314.       finalPosition = GlobalWind(finalPosition, treePos, true, rotatedWindVector, _ST_WindGlobal.x);
  315.     }
  316. #endif
  317.  
  318.     data.vertex.xyz = finalPosition;
  319.   }
  320.  
  321.   void SpeedTreeVertPepe(inout SpeedTreeVB IN, out Input OUT)
  322.   {
  323.     UNITY_INITIALIZE_OUTPUT(Input, OUT);
  324.  
  325.     OUT.mainTexUV = IN.texcoord.xy;
  326.     OUT.color = _Color;
  327.     OUT.color.rgb *= IN.color.r; // ambient occlusion factor
  328.  
  329. #ifdef EFFECT_HUE_VARIATION
  330.     float hueVariationAmount = frac(unity_ObjectToWorld[0].w + unity_ObjectToWorld[1].w + unity_ObjectToWorld[2].w);
  331.     hueVariationAmount += frac(IN.vertex.x + IN.normal.y + IN.normal.x) * 0.5 - 0.3;
  332.     OUT.HueVariationAmount = saturate(hueVariationAmount * _HueVariation.a);
  333. #endif
  334.  
  335. #ifdef GEOM_TYPE_BRANCH_DETAIL
  336.     // The two types are always in different sub-range of the mesh so no interpolation (between detail and blend) problem.
  337.     OUT.Detail.xy = IN.texcoord2.xy;
  338.     if (IN.color.a == 0) // Blend
  339.       OUT.Detail.z = IN.texcoord2.z;
  340.     else // Detail texture
  341.       OUT.Detail.z = 2.5f; // stay out of Blend's .z range
  342. #endif
  343.  
  344.     OffsetSpeedTreeVertexShadow(IN, unity_LODFade.x);
  345.  
  346.     UNITY_TRANSFER_DITHER_CROSSFADE(OUT, IN.vertex)
  347.   }
  348.  
  349.  
  350.   struct v2f
  351.   {
  352.     V2F_SHADOW_CASTER;
  353. #ifdef SPEEDTREE_ALPHATEST
  354.     float2 uv : TEXCOORD1;
  355. #endif
  356.     UNITY_DITHER_CROSSFADE_COORDS_IDX(2)
  357.     UNITY_VERTEX_INPUT_INSTANCE_ID
  358.     UNITY_VERTEX_OUTPUT_STEREO
  359.   };
  360.  
  361.   v2f vert(SpeedTreeVB v)
  362.   {
  363.     v2f o;
  364.     UNITY_SETUP_INSTANCE_ID(v);
  365.     UNITY_TRANSFER_INSTANCE_ID(v, o);
  366.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  367. #ifdef SPEEDTREE_ALPHATEST
  368.     o.uv = v.texcoord.xy;
  369. #endif
  370.     OffsetSpeedTreeVertexShadow(v, unity_LODFade.x);
  371.     TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
  372.     UNITY_TRANSFER_DITHER_CROSSFADE_HPOS(o, o.pos)
  373.     return o;
  374.   }
  375.  
  376.   float4 frag(v2f i) : SV_Target
  377.   {
  378.     UNITY_SETUP_INSTANCE_ID(i);
  379. #ifdef SPEEDTREE_ALPHATEST
  380.   clip(tex2D(_MainTex, i.uv).a * _Color.a - _Cutoff);
  381. #endif
  382.   UNITY_APPLY_DITHER_CROSSFADE(i)
  383.     SHADOW_CASTER_FRAGMENT(i)
  384.   }
  385.     ENDCG
  386.   }
  387.  
  388.   //---------------------------------------------------------------------------------------------------------------------------------
  389.   // Vertex Lighting
  390.   //---------------------------------------------------------------------------------------------------------------------------------
  391.     Pass
  392.   {
  393.     Tags{ "LightMode" = "Vertex" }
  394.  
  395.     CGPROGRAM
  396.     #pragma vertex vert
  397.     #pragma fragment frag
  398.     #pragma target 3.0
  399.     #pragma multi_compile_fog
  400.     #pragma multi_compile  LOD_FADE_PERCENTAGE LOD_FADE_CROSSFADE
  401.     #pragma multi_compile_instancing
  402.     #pragma instancing_options assumeuniformscaling lodfade maxcount:50
  403.     #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  404.     #pragma shader_feature EFFECT_HUE_VARIATION
  405.     #define ENABLE_WIND
  406.     #include "SpeedTreeCommon.cginc"
  407.  
  408.     struct v2f
  409.   {
  410.     float4 vertex   : SV_POSITION;
  411.     UNITY_FOG_COORDS(0)
  412.     Input data : TEXCOORD1;
  413.     UNITY_VERTEX_INPUT_INSTANCE_ID
  414.     UNITY_VERTEX_OUTPUT_STEREO
  415.   };
  416.  
  417.   v2f vert(SpeedTreeVB v)
  418.   {
  419.     v2f o;
  420.     UNITY_SETUP_INSTANCE_ID(v);
  421.     UNITY_TRANSFER_INSTANCE_ID(v, o);
  422.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  423.     SpeedTreeVert(v, o.data);
  424.     o.data.color.rgb *= ShadeVertexLightsFull(v.vertex, v.normal, 4, true);
  425.     o.vertex = UnityObjectToClipPos(v.vertex);
  426.     UNITY_TRANSFER_FOG(o,o.vertex);
  427.     return o;
  428.   }
  429.  
  430.   fixed4 frag(v2f i) : SV_Target
  431.   {
  432.     UNITY_SETUP_INSTANCE_ID(i);
  433.     SpeedTreeFragOut o;
  434.     SpeedTreeFrag(i.data, o);
  435.     fixed4 c = fixed4(o.Albedo, o.Alpha);
  436.     UNITY_APPLY_FOG(i.fogCoord, c);
  437.     return c;
  438.   }
  439.     ENDCG
  440.   }
  441.   }
  442.  
  443.   //---------------------------------------------------------------------------------------------------------------------------------
  444.   // SM 2.0
  445.   //---------------------------------------------------------------------------------------------------------------------------------
  446.  
  447.   // targeting SM2.0: Cross-fading, Normal-mapping, Hue variation and Wind animation are turned off for less instructions
  448.   SubShader
  449.   {
  450.     Tags
  451.   {
  452.     "Queue" = "Geometry"
  453.     "IgnoreProjector" = "True"
  454.     "RenderType" = "Opaque"
  455.     "DisableBatching" = "LODFading"
  456.   }
  457.     LOD 400
  458.     Cull[_Cull]
  459.  
  460.     CGPROGRAM
  461.     #pragma surface surf Lambert vertex:SpeedTreeVertPepe nodirlightmap nodynlightmap noshadowmask
  462.     #pragma multi_compile  LOD_FADE_PERCENTAGE
  463.     #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  464.     #include "SpeedTreeCommon.cginc"
  465.  
  466.     void OffsetSpeedTreeVertexPepe(inout SpeedTreeVB data, float lodValue)
  467.   {
  468.     float3 finalPosition = data.vertex.xyz;
  469.  
  470. #ifdef ENABLE_WIND
  471.     half windQuality = _WindQuality * _WindEnabled;
  472.  
  473.     float3 rotatedWindVector, rotatedBranchAnchor;
  474.     if (windQuality <= WIND_QUALITY_NONE)
  475.     {
  476.       rotatedWindVector = float3(0.0f, 0.0f, 0.0f);
  477.       rotatedBranchAnchor = float3(0.0f, 0.0f, 0.0f);
  478.     }
  479.     else
  480.     {
  481.       // compute rotated wind parameters
  482.       rotatedWindVector = normalize(mul(_ST_WindVector.xyz, (float3x3)unity_ObjectToWorld));
  483.       rotatedBranchAnchor = normalize(mul(_ST_WindBranchAnchor.xyz, (float3x3)unity_ObjectToWorld)) * _ST_WindBranchAnchor.w;
  484.     }
  485. #endif
  486.  
  487. #if defined(GEOM_TYPE_BRANCH) || defined(GEOM_TYPE_FROND)
  488.  
  489.     // smooth LOD
  490. #ifdef LOD_FADE_PERCENTAGE
  491.     finalPosition = lerp(finalPosition, data.texcoord1.xyz, lodValue);
  492. #endif
  493.  
  494.     // frond wind, if needed
  495. #if defined(ENABLE_WIND) && defined(GEOM_TYPE_FROND)
  496.     if (windQuality == WIND_QUALITY_PALM)
  497.       finalPosition = RippleFrond(finalPosition, data.normal, data.texcoord.x, data.texcoord.y, data.texcoord2.x, data.texcoord2.y, data.texcoord2.z);
  498. #endif
  499.  
  500. #elif defined(GEOM_TYPE_LEAF)
  501.  
  502.     // remove anchor position
  503.     finalPosition -= data.texcoord1.xyz;
  504.  
  505.     bool isFacingLeaf = data.color.a == 0;
  506.     if (isFacingLeaf)
  507.     {
  508. #ifdef LOD_FADE_PERCENTAGE
  509.       finalPosition *= lerp(1.0, data.texcoord1.w, lodValue);
  510. #endif
  511.       //Pepe: Billboard alignmend for VertexLit Pass
  512.       float offsetLen = length(finalPosition);
  513.       //finalPosition = mul(finalPosition.xyz, (float3x3)UNITY_MATRIX_IT_MV); // inv(MV) * finalPosition    // old camera facing (orients to view matrix, bad!!)
  514.  
  515.       //In case you want perfect aligned billboards uncomment this lines
  516.       //We use a modified inverse view matrix to axis align the billboards
  517.       //float3x3 axisMatrix = (float3x3)UNITY_MATRIX_IT_MV;
  518.       //axisMatrix[0].xyz = mul((float3x3)unity_WorldToObject,float3(-1, 0, 0));
  519.       //axisMatrix[1].xyz = float3(0, 1, 0);
  520.       //finalPosition = mul(finalPosition.xyz, (float3x3)axisMatrix);
  521.  
  522.       //We need the viewVector to align the billboards to the cameraposition
  523.       float3 lookAtPoint = mul(unity_ObjectToWorld, float4(data.texcoord1.xyz, data.vertex.w));
  524.       float3 viewVector = normalize(_WorldSpaceCameraPos.xyz - lookAtPoint);
  525.  
  526.       //Then we create a LookAt matrix
  527.       float3 up = float3(0, 1, 0);
  528.       float3 zaxis = viewVector;
  529.       float3 xaxis = normalize(cross(up, zaxis));
  530.       float3 yaxis = cross(zaxis, xaxis);
  531.       float3x3 lookatMatrix = {
  532.         xaxis.x,            yaxis.x,            zaxis.x,
  533.         xaxis.y,            yaxis.y,            zaxis.y,
  534.         xaxis.z,            yaxis.z,            zaxis.z
  535.       };
  536.       //...and apply the rotation!
  537.       finalPosition = mul(lookatMatrix, finalPosition);
  538.  
  539.       finalPosition = normalize(finalPosition) * offsetLen; // make sure the offset vector is still scaled
  540.     }
  541.     else
  542.     {
  543. #ifdef LOD_FADE_PERCENTAGE
  544.       float3 lodPosition = float3(data.texcoord1.w, data.texcoord3.x, data.texcoord3.y);
  545.       finalPosition = lerp(finalPosition, lodPosition, lodValue);
  546. #endif
  547.     }
  548.  
  549. #ifdef ENABLE_WIND
  550.     // leaf wind
  551.     if (windQuality > WIND_QUALITY_FASTEST && windQuality < WIND_QUALITY_PALM)
  552.     {
  553.       float leafWindTrigOffset = data.texcoord1.x + data.texcoord1.y;
  554.       finalPosition = LeafWind(windQuality == WIND_QUALITY_BEST, data.texcoord2.w > 0.0, finalPosition, data.normal, data.texcoord2.x, float3(0,0,0), data.texcoord2.y, data.texcoord2.z, leafWindTrigOffset, rotatedWindVector);
  555.     }
  556. #endif
  557.  
  558.     // move back out to anchor
  559.     finalPosition += data.texcoord1.xyz;
  560.  
  561. #endif
  562.  
  563. #ifdef ENABLE_WIND
  564.     float3 treePos = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
  565.  
  566. #ifndef GEOM_TYPE_MESH
  567.     if (windQuality >= WIND_QUALITY_BETTER)
  568.     {
  569.       // branch wind (applies to all 3D geometry)
  570.       finalPosition = BranchWind(windQuality == WIND_QUALITY_PALM, finalPosition, treePos, float4(data.texcoord.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor);
  571.     }
  572. #endif
  573.  
  574.     if (windQuality > WIND_QUALITY_NONE)
  575.     {
  576.       // global wind
  577.       finalPosition = GlobalWind(finalPosition, treePos, true, rotatedWindVector, _ST_WindGlobal.x);
  578.     }
  579. #endif
  580.  
  581.     data.vertex.xyz = finalPosition;
  582.   }
  583.  
  584.   void SpeedTreeVertPepe(inout SpeedTreeVB IN, out Input OUT)
  585.   {
  586.     UNITY_INITIALIZE_OUTPUT(Input, OUT);
  587.  
  588.     OUT.mainTexUV = IN.texcoord.xy;
  589.     OUT.color = _Color;
  590.     OUT.color.rgb *= IN.color.r; // ambient occlusion factor
  591.  
  592. #ifdef EFFECT_HUE_VARIATION
  593.     float hueVariationAmount = frac(unity_ObjectToWorld[0].w + unity_ObjectToWorld[1].w + unity_ObjectToWorld[2].w);
  594.     hueVariationAmount += frac(IN.vertex.x + IN.normal.y + IN.normal.x) * 0.5 - 0.3;
  595.     OUT.HueVariationAmount = saturate(hueVariationAmount * _HueVariation.a);
  596. #endif
  597.  
  598. #ifdef GEOM_TYPE_BRANCH_DETAIL
  599.     // The two types are always in different sub-range of the mesh so no interpolation (between detail and blend) problem.
  600.     OUT.Detail.xy = IN.texcoord2.xy;
  601.     if (IN.color.a == 0) // Blend
  602.       OUT.Detail.z = IN.texcoord2.z;
  603.     else // Detail texture
  604.       OUT.Detail.z = 2.5f; // stay out of Blend's .z range
  605. #endif
  606.  
  607.     OffsetSpeedTreeVertexPepe(IN, unity_LODFade.x);
  608.  
  609.     UNITY_TRANSFER_DITHER_CROSSFADE(OUT, IN.vertex)
  610.   }
  611.  
  612.   void surf(Input IN, inout SurfaceOutput OUT)
  613.   {
  614.     SpeedTreeFragOut o;
  615.     SpeedTreeFrag(IN, o);
  616.     SPEEDTREE_COPY_FRAG(OUT, o)
  617.   }
  618.   ENDCG
  619.  
  620.     //---------------------------------------------------------------------------------------------------------------------------------
  621.     // Shadow Caster
  622.     //---------------------------------------------------------------------------------------------------------------------------------
  623.  
  624.     Pass
  625.     {
  626.     Tags{ "LightMode" = "ShadowCaster" }
  627.  
  628.     CGPROGRAM
  629.     #pragma vertex vert
  630.     #pragma fragment frag
  631.  
  632.     #pragma multi_compile  LOD_FADE_PERCENTAGE
  633.     #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  634.     #pragma multi_compile_shadowcaster
  635.     #include "SpeedTreeCommon.cginc"
  636.  
  637.     void OffsetSpeedTreeVertexShadow(inout SpeedTreeVB data, float lodValue)
  638.     {
  639.     float3 finalPosition = data.vertex.xyz;
  640.  
  641. #ifdef ENABLE_WIND
  642.     half windQuality = _WindQuality * _WindEnabled;
  643.  
  644.     float3 rotatedWindVector, rotatedBranchAnchor;
  645.     if (windQuality <= WIND_QUALITY_NONE)
  646.     {
  647.       rotatedWindVector = float3(0.0f, 0.0f, 0.0f);
  648.       rotatedBranchAnchor = float3(0.0f, 0.0f, 0.0f);
  649.     }
  650.     else
  651.     {
  652.       // compute rotated wind parameters
  653.       rotatedWindVector = normalize(mul(_ST_WindVector.xyz, (float3x3)unity_ObjectToWorld));
  654.       rotatedBranchAnchor = normalize(mul(_ST_WindBranchAnchor.xyz, (float3x3)unity_ObjectToWorld)) * _ST_WindBranchAnchor.w;
  655.     }
  656. #endif
  657.  
  658. #if defined(GEOM_TYPE_BRANCH) || defined(GEOM_TYPE_FROND)
  659.  
  660.     // smooth LOD
  661. #ifdef LOD_FADE_PERCENTAGE
  662.     finalPosition = lerp(finalPosition, data.texcoord1.xyz, lodValue);
  663. #endif
  664.  
  665.     // frond wind, if needed
  666. #if defined(ENABLE_WIND) && defined(GEOM_TYPE_FROND)
  667.     if (windQuality == WIND_QUALITY_PALM)
  668.       finalPosition = RippleFrond(finalPosition, data.normal, data.texcoord.x, data.texcoord.y, data.texcoord2.x, data.texcoord2.y, data.texcoord2.z);
  669. #endif
  670.  
  671. #elif defined(GEOM_TYPE_LEAF)
  672.  
  673.     // remove anchor position
  674.     finalPosition -= data.texcoord1.xyz;
  675.  
  676.     bool isFacingLeaf = data.color.a == 0;
  677.     if (isFacingLeaf)
  678.     {
  679. #ifdef LOD_FADE_PERCENTAGE
  680.       finalPosition *= lerp(1.0, data.texcoord1.w, lodValue);
  681. #endif
  682.       //Pepe: ShadowCaster Pass - We don't apply any Billboard Transforms here
  683.       // face camera-facing leaf to camera
  684.       // float offsetLen = length(finalPosition);
  685.       // finalPosition = mul(finalPosition.xyz, (float3x3)UNITY_MATRIX_IT_MV); // inv(MV) * finalPosition    // old camera facing (orients to view matrix, bad!)
  686.       // finalPosition = normalize(finalPosition) * offsetLen; // make sure the offset vector is still scaled
  687.     }
  688.     else
  689.     {
  690. #ifdef LOD_FADE_PERCENTAGE
  691.       float3 lodPosition = float3(data.texcoord1.w, data.texcoord3.x, data.texcoord3.y);
  692.       finalPosition = lerp(finalPosition, lodPosition, lodValue);
  693. #endif
  694.     }
  695.  
  696. #ifdef ENABLE_WIND
  697.     // leaf wind
  698.     if (windQuality > WIND_QUALITY_FASTEST && windQuality < WIND_QUALITY_PALM)
  699.     {
  700.       float leafWindTrigOffset = data.texcoord1.x + data.texcoord1.y;
  701.       finalPosition = LeafWind(windQuality == WIND_QUALITY_BEST, data.texcoord2.w > 0.0, finalPosition, data.normal, data.texcoord2.x, float3(0,0,0), data.texcoord2.y, data.texcoord2.z, leafWindTrigOffset, rotatedWindVector);
  702.     }
  703. #endif
  704.  
  705.     // move back out to anchor
  706.     finalPosition += data.texcoord1.xyz;
  707.  
  708. #endif
  709.  
  710. #ifdef ENABLE_WIND
  711.     float3 treePos = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
  712.  
  713. #ifndef GEOM_TYPE_MESH
  714.     if (windQuality >= WIND_QUALITY_BETTER)
  715.     {
  716.       // branch wind (applies to all 3D geometry)
  717.       finalPosition = BranchWind(windQuality == WIND_QUALITY_PALM, finalPosition, treePos, float4(data.texcoord.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor);
  718.     }
  719. #endif
  720.  
  721.     if (windQuality > WIND_QUALITY_NONE)
  722.     {
  723.       // global wind
  724.       finalPosition = GlobalWind(finalPosition, treePos, true, rotatedWindVector, _ST_WindGlobal.x);
  725.     }
  726. #endif
  727.  
  728.     data.vertex.xyz = finalPosition;
  729.   }
  730.  
  731.   /*
  732.   void SpeedTreeVertShadow(inout SpeedTreeVB IN, out Input OUT)
  733.   {
  734.     UNITY_INITIALIZE_OUTPUT(Input, OUT);
  735.  
  736.     OUT.mainTexUV = IN.texcoord.xy;
  737.     OUT.color = _Color;
  738.     OUT.color.rgb *= IN.color.r; // ambient occlusion factor
  739.  
  740. #ifdef EFFECT_HUE_VARIATION
  741.     float hueVariationAmount = frac(unity_ObjectToWorld[0].w + unity_ObjectToWorld[1].w + unity_ObjectToWorld[2].w);
  742.     hueVariationAmount += frac(IN.vertex.x + IN.normal.y + IN.normal.x) * 0.5 - 0.3;
  743.     OUT.HueVariationAmount = saturate(hueVariationAmount * _HueVariation.a);
  744. #endif
  745.  
  746. #ifdef GEOM_TYPE_BRANCH_DETAIL
  747.     // The two types are always in different sub-range of the mesh so no interpolation (between detail and blend) problem.
  748.     OUT.Detail.xy = IN.texcoord2.xy;
  749.     if (IN.color.a == 0) // Blend
  750.       OUT.Detail.z = IN.texcoord2.z;
  751.     else // Detail texture
  752.       OUT.Detail.z = 2.5f; // stay out of Blend's .z range
  753. #endif
  754.  
  755.     OffsetSpeedTreeVertexShadow(IN, unity_LODFade.x);
  756.  
  757.     UNITY_TRANSFER_DITHER_CROSSFADE(OUT, IN.vertex)
  758.   }
  759.   */
  760.  
  761.   struct v2f
  762.   {
  763.     V2F_SHADOW_CASTER;
  764.     #ifdef SPEEDTREE_ALPHATEST
  765.        float2 uv : TEXCOORD1;
  766.     #endif
  767.   };
  768.  
  769.   v2f vert(SpeedTreeVB v)
  770.   {
  771.     v2f o;
  772.     #ifdef SPEEDTREE_ALPHATEST
  773.       o.uv = v.texcoord.xy;
  774.     #endif
  775.     OffsetSpeedTreeVertexShadow(v, unity_LODFade.x);
  776.     TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
  777.    return o;
  778.   }
  779.  
  780.   float4 frag(v2f i) : SV_Target
  781.   {
  782.   #ifdef SPEEDTREE_ALPHATEST
  783.     clip(tex2D(_MainTex, i.uv).a * _Color.a - _Cutoff);
  784.   #endif
  785.   SHADOW_CASTER_FRAGMENT(i)
  786.   }
  787.     ENDCG
  788.   }
  789.  
  790.   //---------------------------------------------------------------------------------------------------------------------------------
  791.   // Vertex Lightmode
  792.   //---------------------------------------------------------------------------------------------------------------------------------
  793.  
  794.   Pass
  795.   {
  796.     Tags{ "LightMode" = "Vertex" }
  797.  
  798.     CGPROGRAM
  799.     #pragma vertex vert
  800.     #pragma fragment frag
  801.     #pragma multi_compile_fog
  802.     #pragma multi_compile  LOD_FADE_PERCENTAGE
  803.     #pragma shader_feature GEOM_TYPE_BRANCH GEOM_TYPE_BRANCH_DETAIL GEOM_TYPE_FROND GEOM_TYPE_LEAF GEOM_TYPE_MESH
  804.     #include "SpeedTreeCommon.cginc"
  805.  
  806.   struct v2f
  807.   {
  808.     float4 vertex   : SV_POSITION;
  809.     UNITY_FOG_COORDS(0)
  810.     Input data : TEXCOORD1;
  811.     UNITY_VERTEX_OUTPUT_STEREO
  812.   };
  813.  
  814.   v2f vert(SpeedTreeVB v)
  815.   {
  816.     v2f o;
  817.     UNITY_SETUP_INSTANCE_ID(v);
  818.     UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  819.     SpeedTreeVert(v, o.data);
  820.     o.data.color.rgb *= ShadeVertexLightsFull(v.vertex, v.normal, 2, false);
  821.     o.vertex = UnityObjectToClipPos(v.vertex);
  822.     UNITY_TRANSFER_FOG(o,o.vertex);
  823.     return o;
  824.   }
  825.  
  826.   fixed4 frag(v2f i) : SV_Target
  827.   {
  828.     SpeedTreeFragOut o;
  829.     SpeedTreeFrag(i.data, o);
  830.     fixed4 c = fixed4(o.Albedo, o.Alpha);
  831.     UNITY_APPLY_FOG(i.fogCoord, c);
  832.     return c;
  833.   }
  834.     ENDCG
  835.   }
  836.   }
  837.  
  838.     FallBack "Transparent/Cutout/VertexLit"
  839.     CustomEditor "SpeedTreeMaterialInspector"
  840. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top