Advertisement
Guest User

GrassGeometry.shader

a guest
Jan 28th, 2021
13,443
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. Shader "Custom/Grass Geometry Shader 3" {
  3.     Properties{
  4.         _BottomColor("Bottom Color", Color) = (0,1,0,1)
  5.         _TopColor("Top Color", Color) = (1,1,0,1)
  6.         _GrassHeight("Grass Height", Float) = 1
  7.         _GrassWidth("Grass Width", Float) = 0.06
  8.         _RandomHeight("Grass Height Randomness", Float) = 0.25
  9.         _WindSpeed("Wind Speed", Float) = 100
  10.         _WindStrength("Wind Strength", Float) = 0.05
  11.         _Radius("Interactor Radius", Float) = 0.3
  12.         _Strength("Interactor Strength", Float) = 5
  13.         _Rad("Blade Radius", Range(0,1)) = 0.6
  14.         _BladeForward("Blade Forward Amount", Float) = 0.38
  15.         _BladeCurve("Blade Curvature Amount", Range(1, 4)) = 2
  16.         _AmbientStrength("Ambient Strength",  Range(0,1)) = 0.5
  17.         _MinDist("Min Distance", Float) = 40
  18.         _MaxDist("Max Distance", Float) = 60
  19.     }
  20.  
  21.  
  22.         CGINCLUDE
  23. #include "UnityCG.cginc"
  24. #include "Lighting.cginc"
  25. #include "AutoLight.cginc"
  26. #pragma multi_compile _SHADOWS_SCREEN
  27. #pragma multi_compile_fwdbase_fullforwardshadows
  28. #pragma multi_compile_fog
  29. #define GrassSegments 5 // segments per blade
  30. #define GrassBlades 4 // blades per vertex
  31.  
  32.         struct v2g
  33.     {
  34.         float4 pos : SV_POSITION;
  35.         float3 norm : NORMAL;
  36.         float2 uv : TEXCOORD0;
  37.         float3 color : COLOR;
  38.  
  39.  
  40.     };
  41.  
  42.     struct g2f
  43.     {
  44.         float4 pos : SV_POSITION;
  45.         float3 norm : NORMAL;
  46.         float2 uv : TEXCOORD0;
  47.         float3 diffuseColor : COLOR;
  48.         float3 worldPos : TEXCOORD3;
  49.         LIGHTING_COORDS(5, 6)
  50.             UNITY_FOG_COORDS(4)
  51.     };
  52.  
  53.     half _GrassHeight;
  54.     half _GrassWidth;
  55.     half _WindSpeed;
  56.     float _WindStrength;
  57.     half _Radius, _Strength;
  58.     float _Rad;
  59.  
  60.     float _RandomHeight;
  61.     float _BladeForward;
  62.     float _BladeCurve;
  63.  
  64.     float _MinDist, _MaxDist;
  65.  
  66.     uniform float3 _PositionMoving;
  67.  
  68.     v2g vert(appdata_full v)
  69.     {
  70.         float3 v0 = v.vertex.xyz;
  71.  
  72.         v2g OUT;
  73.         OUT.pos = v.vertex;
  74.         OUT.norm = v.normal;
  75.         OUT.uv = v.texcoord;
  76.         OUT.color = v.color;
  77.         return OUT;
  78.     }
  79.  
  80.     float rand(float3 co)
  81.     {
  82.         return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
  83.     }
  84.  
  85.     // Construct a rotation matrix that rotates around the provided axis, sourced from:
  86. // https://gist.github.com/keijiro/ee439d5e7388f3aafc5296005c8c3f33
  87.     float3x3 AngleAxis3x3(float angle, float3 axis)
  88.     {
  89.         float c, s;
  90.         sincos(angle, s, c);
  91.  
  92.         float t = 1 - c;
  93.         float x = axis.x;
  94.         float y = axis.y;
  95.         float z = axis.z;
  96.  
  97.         return float3x3(
  98.             t * x * x + c, t * x * y - s * z, t * x * z + s * y,
  99.             t * x * y + s * z, t * y * y + c, t * y * z - s * x,
  100.             t * x * z - s * y, t * y * z + s * x, t * z * z + c
  101.             );
  102.     }
  103.  
  104.     // hack because TRANSFER_VERTEX_TO_FRAGMENT has harcoded requirement for 'v.vertex'
  105.     struct unityTransferVertexToFragmentHack
  106.     {
  107.         float3 vertex : POSITION;
  108.     };
  109.  
  110.     // per new grass vertex
  111.     g2f GrassVertex(float3 vertexPos, float width, float height, float offset, float curve, float2 uv, float3x3 rotation, float3 faceNormal, float3 color, float3 worldPos) {
  112.         g2f OUT;
  113.         OUT.pos = UnityObjectToClipPos(vertexPos + mul(rotation, float3(width, height, curve) + float3(0, 0, offset)));
  114.         OUT.norm = faceNormal;
  115.         OUT.diffuseColor = color;
  116.         OUT.uv = uv;
  117.         OUT.worldPos = worldPos;
  118.  
  119.         // send extra vertex to forwardadd pass
  120.         unityTransferVertexToFragmentHack v;
  121.         v.vertex = vertexPos + mul(rotation, float3(width, height, curve) + float3(0, 0, offset));
  122.         TRANSFER_VERTEX_TO_FRAGMENT(OUT);
  123.         UNITY_TRANSFER_FOG(OUT, OUT.pos);
  124.         return OUT;
  125.     }
  126.  
  127.     // wind and basic grassblade setup from https://roystan.net/articles/grass-shader.html
  128.     // limit for vertices
  129.     [maxvertexcount(51)]
  130.     void geom(point v2g IN[1], inout TriangleStream<g2f> triStream)
  131.     {
  132.  
  133.  
  134.  
  135.         float forward = rand(IN[0].pos.yyz) * _BladeForward;
  136.         float3 lightPosition = _WorldSpaceLightPos0;
  137.  
  138.         float3 perpendicularAngle = float3(0, 0, 1);
  139.         float3 faceNormal = cross(perpendicularAngle, IN[0].norm) * lightPosition;
  140.  
  141.         float4 worldPos = mul(unity_ObjectToWorld, IN[0].pos);
  142.  
  143.         // camera distance for culling
  144.         float distanceFromCamera = distance(worldPos, _WorldSpaceCameraPos);
  145.         float distanceFade = 1 - saturate((distanceFromCamera - _MinDist) / _MaxDist);
  146.  
  147.         float3 v0 = IN[0].pos.xyz;
  148.  
  149.         float3 wind1 = float3(sin(_Time.x * _WindSpeed + v0.x) + sin(_Time.x * _WindSpeed + v0.z * 2) + sin(_Time.x * _WindSpeed * 0.1 + v0.x), 0,
  150.             cos(_Time.x * _WindSpeed + v0.x * 2) + cos(_Time.x * _WindSpeed + v0.z));
  151.  
  152.         wind1 *= _WindStrength;
  153.  
  154.  
  155.         // Interactivity
  156.         float3 dis = distance(_PositionMoving, worldPos); // distance for radius
  157.         float3 radius = 1 - saturate(dis / _Radius); // in world radius based on objects interaction radius
  158.         float3 sphereDisp = worldPos - _PositionMoving; // position comparison
  159.         sphereDisp *= radius; // position multiplied by radius for falloff
  160.         // increase strength
  161.         sphereDisp = clamp(sphereDisp.xyz * _Strength, -0.8, 0.8);
  162.  
  163.         // set vertex color
  164.         float3 color = (IN[0].color);
  165.         // set grass height
  166.         _GrassHeight *= IN[0].uv.y;
  167.         _GrassWidth *= IN[0].uv.x;
  168.         _GrassHeight *= clamp(rand(IN[0].pos.xyz), 1 - _RandomHeight, 1 + _RandomHeight);
  169.  
  170.         // grassblades geometry
  171.         for (int j = 0; j < (GrassBlades * distanceFade); j++)
  172.         {
  173.             // set rotation and radius of the blades
  174.             float3x3 facingRotationMatrix = AngleAxis3x3(rand(IN[0].pos.xyz) * UNITY_TWO_PI + j, float3(0, 1, -0.1));
  175.             float3x3 transformationMatrix = facingRotationMatrix;
  176.             float radius = j / (float)GrassBlades;
  177.             float offset = (1 - radius) * _Rad;
  178.             for (int i = 0; i < GrassSegments; i++)
  179.             {
  180.                 // taper width, increase height;
  181.                 float t = i / (float)GrassSegments;
  182.                 float segmentHeight = _GrassHeight * t;
  183.                 float segmentWidth = _GrassWidth * (1 - t);
  184.  
  185.                 // the first (0) grass segment is thinner
  186.                 segmentWidth = i == 0 ? _GrassWidth * 0.3 : segmentWidth;
  187.  
  188.                 float segmentForward = pow(t, _BladeCurve) * forward;
  189.  
  190.                 // Add below the line declaring float segmentWidth.
  191.                 float3x3 transformMatrix = i == 0 ? facingRotationMatrix : transformationMatrix;
  192.  
  193.                 // first grass (0) segment does not get displaced by interactivity
  194.                 float3 newPos = i == 0 ? v0 : v0 + ((float3(sphereDisp.x, sphereDisp.y, sphereDisp.z) + wind1) * t);
  195.  
  196.                 // every segment adds 2 new triangles
  197.                 triStream.Append(GrassVertex(newPos, segmentWidth, segmentHeight, offset, segmentForward, float2(0, t), transformMatrix, faceNormal, color, worldPos));
  198.                 triStream.Append(GrassVertex(newPos, -segmentWidth, segmentHeight, offset, segmentForward, float2(1, t), transformMatrix, faceNormal, color, worldPos));
  199.  
  200.  
  201.  
  202.             }
  203.             // Add just below the loop to insert the vertex at the tip of the blade.
  204.             triStream.Append(GrassVertex(v0 + float3(sphereDisp.x * 1.5, sphereDisp.y, sphereDisp.z * 1.5) + wind1, 0, _GrassHeight, offset, forward, float2(0.5, 1), transformationMatrix, faceNormal, color, worldPos));
  205.             // restart the strip to start another grass blade
  206.             triStream.RestartStrip();
  207.         }
  208.     }
  209.  
  210.  
  211.     ENDCG
  212.         SubShader
  213.     {
  214.         Cull Off
  215.  
  216.             Pass // basic color with directional lights
  217.             {
  218.                 Tags
  219.                 {
  220.                     "RenderType" = "Geometry"
  221.                     "LightMode" = "ForwardBase"
  222.                 }
  223.  
  224.             CGPROGRAM
  225.             #pragma vertex vert
  226.             #pragma fragment frag
  227.             #pragma geometry geom
  228.             #pragma target 4.6
  229.             #pragma multi_compile_fwdbase_fullforwardshadows
  230.  
  231.             float4 _TopColor;
  232.             float4 _BottomColor;
  233.             float _AmbientStrength;
  234.  
  235.             float4 frag(g2f i) : SV_Target
  236.             {
  237.                 // take shadow data
  238.             float shadow = 1;
  239. #if defined(SHADOWS_SCREEN)
  240.             shadow = (SAMPLE_DEPTH_TEXTURE_PROJ(_ShadowMapTexture, UNITY_PROJ_COORD(i._ShadowCoord)).r);
  241. #endif         
  242.             // base color by lerping 2 colors over the UVs
  243.             float4 baseColor = lerp(_BottomColor , _TopColor , saturate(i.uv.y)) * float4(i.diffuseColor, 1);
  244.             // multiply with lighting color
  245.             float4 litColor = (baseColor * _LightColor0);
  246.             // multiply with vertex color, and shadows
  247.             float4 final = litColor * shadow;
  248.             // add in basecolor when lights turned off
  249.             final += saturate((1 - shadow) * baseColor * 0.2);
  250.             // add in ambient color
  251.             final += (unity_AmbientSky * baseColor * _AmbientStrength);
  252.             // add fog
  253.             UNITY_APPLY_FOG(i.fogCoord, final);
  254.             return final;
  255.             }
  256.             ENDCG
  257.         }
  258.  
  259.             Pass
  260.                 // point lights
  261.             {
  262.                 Tags
  263.                 {
  264.                     "LightMode" = "ForwardAdd"
  265.                 }
  266.                 Blend OneMinusDstColor One
  267.                 ZWrite Off
  268.  
  269.             CGPROGRAM
  270.             #pragma vertex vert
  271.             #pragma geometry geom
  272.             #pragma fragment frag                                  
  273.             #pragma multi_compile_fwdadd_fullforwardshadows
  274.  
  275.             float4 frag(g2f i) : SV_Target
  276.             {
  277.                     UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
  278.  
  279.                     float3 pointlights = atten * _LightColor0.rgb;
  280.  
  281.                     return float4(pointlights, 1);
  282.                 }
  283.             ENDCG
  284.             }
  285.  
  286.         Pass // shadow pass
  287.             {
  288.                 Tags
  289.                 {
  290.                     "LightMode" = "ShadowCaster"
  291.                 }
  292.  
  293.                     CGPROGRAM
  294.                     #pragma vertex vert
  295.                     #pragma geometry geom
  296.                     #pragma fragment frag
  297.                     #pragma multi_compile_shadowcaster
  298.  
  299.                     float4 frag(g2f i) : SV_Target
  300.                     {
  301.  
  302.                         SHADOW_CASTER_FRAGMENT(i)
  303.                     }
  304.                     ENDCG
  305.             }
  306.  
  307.  
  308.     }    Fallback "VertexLit"
  309. }
  310.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement