Guest User

GrassGeometryURP

a guest
Mar 19th, 2021
4,833
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Shader "Custom/GeometryGrass"
  2. {
  3.     // The properties block of the Unity shader. In this example this block is empty
  4.     // because the output color is predefined in the fragment shader code.
  5.     Properties
  6.     {
  7.         _BottomColor("Bottom Color", Color) = (0,1,0,1)
  8.         _TopColor("Top Color", Color) = (1,1,0,1)
  9.         _GrassHeight("Grass Height", Float) = 1
  10.         _GrassWidth("Grass Width", Float) = 0.06
  11.         _RandomHeight("Grass Height Randomness", Float) = 0.25
  12.         _WindSpeed("Wind Speed", Float) = 100
  13.         _WindStrength("Wind Strength", Float) = 0.05
  14.         _Radius("Interactor Radius", Float) = 0.3
  15.         _Strength("Interactor Strength", Float) = 5
  16.         _Rad("Blade Radius", Range(0,1)) = 0.6
  17.         _BladeForward("Blade Forward Amount", Float) = 0.38
  18.         _BladeCurve("Blade Curvature Amount", Range(1, 4)) = 2
  19.         _AmbientStrength("Ambient Strength",  Range(0,1)) = 0.5
  20.         _MinDist("Min Distance", Float) = 40
  21.         _MaxDist("Max Distance", Float) = 60
  22.     }
  23.  
  24.         // The HLSL code block. Unity SRP uses the HLSL language.
  25.         HLSLINCLUDE
  26.         // This line defines the name of the vertex shader.
  27. #pragma vertex vert
  28.         // This line defines the name of the fragment shader.
  29. #pragma fragment frag
  30. #pragma require geometry
  31. #pragma geometry geom
  32.  
  33. #define GrassSegments 5 // segments per blade
  34. #define GrassBlades 4 // blades per vertex
  35.  
  36. #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
  37. #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
  38.  
  39. #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
  40. #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
  41. #pragma multi_compile_fragment _ _SHADOWS_SOFT
  42. #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
  43. #pragma multi_compile _ SHADOWS_SHADOWMASK
  44. #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
  45. #pragma multi_compile_fog  
  46. #pragma multi_compile _ DIRLIGHTMAP_COMBINED
  47. #pragma multi_compile _ LIGHTMAP_ON
  48.  
  49.         // The Core.hlsl file contains definitions of frequently used HLSL
  50.         // macros and functions, and also contains #include references to other
  51.         // HLSL files (for example, Common.hlsl, SpaceTransforms.hlsl, etc.).
  52.  
  53. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  54. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
  55. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
  56.  
  57.         // The structure definition defines which variables it contains.
  58.         // This example uses the Attributes structure as an input structure in
  59.         // the vertex shader.
  60.         struct Attributes
  61.     {
  62.         // The positionOS variable contains the vertex positions in object
  63.         // space.
  64.         float4 positionOS   : POSITION;
  65.         float3 normal :NORMAL;
  66.         float2 texcoord : TEXCOORD0;
  67.         float4 color : COLOR;
  68.         float4 tangent :TANGENT;
  69.     };
  70.  
  71.     struct v2g
  72.     {
  73.         float4 pos : SV_POSITION;
  74.         float3 norm : NORMAL;
  75.         float2 uv : TEXCOORD0;
  76.         float4 color : COLOR;
  77.         float4 tangent : TANGENT;
  78.  
  79.  
  80.     };
  81.  
  82.     half _GrassHeight;
  83.     half _GrassWidth;
  84.     half _WindSpeed;
  85.     float _WindStrength;
  86.     half _Radius, _Strength;
  87.     float _Rad;
  88.  
  89.     float _RandomHeight;
  90.     float _BladeForward;
  91.     float _BladeCurve;
  92.  
  93.     float _MinDist, _MaxDist;
  94.  
  95.     uniform float3 _PositionMoving;
  96.  
  97.     v2g vert(Attributes v)
  98.     {
  99.         float3 v0 = v.positionOS.xyz;
  100.  
  101.         v2g OUT;
  102.         OUT.pos = v.positionOS;
  103.         OUT.norm = v.normal;
  104.         OUT.uv = v.texcoord;
  105.         OUT.color = v.color;
  106.  
  107.         OUT.norm = TransformObjectToWorldNormal(v.normal);
  108.         OUT.tangent = v.tangent;
  109.         return OUT;
  110.     }
  111.  
  112.     struct g2f
  113.     {
  114.         float4 pos : SV_POSITION;
  115.         float3 norm : NORMAL;
  116.         float2 uv : TEXCOORD0;
  117.         float3 diffuseColor : COLOR;
  118.         float3 worldPos : TEXCOORD3;
  119.         float fogFactor : TEXCOORD5;
  120.  
  121.     };
  122.  
  123.     float rand(float3 co)
  124.     {
  125.         return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
  126.     }
  127.  
  128.     // Construct a rotation matrix that rotates around the provided axis, sourced from:
  129.     // https://gist.github.com/keijiro/ee439d5e7388f3aafc5296005c8c3f33
  130.     float3x3 AngleAxis3x3(float angle, float3 axis)
  131.     {
  132.         float c, s;
  133.         sincos(angle, s, c);
  134.  
  135.         float t = 1 - c;
  136.         float x = axis.x;
  137.         float y = axis.y;
  138.         float z = axis.z;
  139.  
  140.         return float3x3(
  141.             t * x * x + c, t * x * y - s * z, t * x * z + s * y,
  142.             t * x * y + s * z, t * y * y + c, t * y * z - s * x,
  143.             t * x * z - s * y, t * y * z + s * x, t * z * z + c
  144.             );
  145.     }
  146.  
  147.  
  148.     float4 GetShadowPositionHClip(float3 input, float3 normal)
  149.     {
  150.         float3 positionWS = TransformObjectToWorld(input.xyz);
  151.         float3 normalWS = TransformObjectToWorldNormal(normal);
  152.  
  153.         float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, 0));
  154.  
  155.  
  156. #if UNITY_REVERSED_Z
  157.         positionCS.z = min(positionCS.z, UNITY_NEAR_CLIP_VALUE);
  158. #else
  159.         positionCS.z = max(positionCS.z, UNITY_NEAR_CLIP_VALUE);
  160. #endif
  161.         return positionCS;
  162.     }
  163.  
  164.     // per new grass vertex
  165.     g2f GrassVertex(float3 vertexPos, float width, float height, float offset, float curve, float2 uv, float3x3 rotation, float3 faceNormal, float3 color) {
  166.         g2f OUT;
  167.         float3 offsetvertices = vertexPos + mul(rotation, float3(width, height, curve) + float3(0, 0, offset));
  168.         OUT.pos = GetShadowPositionHClip(offsetvertices, faceNormal);
  169.         OUT.norm = faceNormal;
  170.         OUT.diffuseColor = color;
  171.         OUT.uv = uv;
  172.         VertexPositionInputs vertexInput = GetVertexPositionInputs(vertexPos + mul(rotation, float3(width, height, curve)));
  173.         OUT.worldPos = vertexInput.positionWS;
  174.         float fogFactor = ComputeFogFactor(OUT.pos.z);
  175.         OUT.fogFactor = fogFactor;
  176.         return OUT;
  177.     }
  178.  
  179.     // wind and basic grassblade setup from https://roystan.net/articles/grass-shader.html
  180.     // limit for vertices
  181.     [maxvertexcount(48)]
  182.     void geom(point v2g IN[1], inout TriangleStream<g2f> triStream)
  183.     {
  184.         float forward = rand(IN[0].pos.yyz) * _BladeForward;
  185.         // just use an up facing normal, works nicest
  186.         float3 faceNormal = float3(0, 1, 0);
  187.         float3 worldPos = TransformObjectToWorld(IN[0].pos.xyz);
  188.         // camera distance for culling
  189.         float distanceFromCamera = distance(worldPos, _WorldSpaceCameraPos);
  190.         float distanceFade = 1 - saturate((distanceFromCamera - _MinDist) / _MaxDist);
  191.         // wind
  192.         float3 v0 = IN[0].pos.xyz;
  193.         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,
  194.             cos(_Time.x * _WindSpeed + v0.x * 2) + cos(_Time.x * _WindSpeed + v0.z));
  195.         wind1 *= _WindStrength;
  196.  
  197.         // Interactivity
  198.         float3 dis = distance(_PositionMoving, worldPos); // distance for radius
  199.         float3 radius = 1 - saturate(dis / _Radius); // in world radius based on objects interaction radius
  200.         float3 sphereDisp = worldPos - _PositionMoving; // position comparison
  201.         sphereDisp *= radius; // position multiplied by radius for falloff
  202.                               // increase strength
  203.         sphereDisp = clamp(sphereDisp.xyz * _Strength, -0.8, 0.8);
  204.  
  205.         // set vertex color
  206.         float3 color = (IN[0].color).rgb;
  207.         // set grass height from tool, uncomment if youre not using the tool!
  208.         _GrassHeight *= IN[0].uv.y;
  209.         _GrassWidth *= IN[0].uv.x;
  210.         _GrassHeight *= clamp(rand(IN[0].pos.xyz), 1 - _RandomHeight, 1 + _RandomHeight);
  211.  
  212.         // grassblades geometry
  213.         for (int j = 0; j < (GrassBlades * distanceFade); j++)
  214.         {
  215.             // set rotation and radius of the blades
  216.             float3x3 facingRotationMatrix = AngleAxis3x3(rand(IN[0].pos.xyz) * TWO_PI + j, float3(0, 1, -0.1));
  217.  
  218.             float3x3 transformationMatrix = facingRotationMatrix;
  219.  
  220.             faceNormal = mul(faceNormal, transformationMatrix);
  221.             float radius = j / (float)GrassBlades;
  222.             float offset = (1 - radius) * _Rad;
  223.             for (int i = 0; i < GrassSegments; i++)
  224.             {
  225.                 // taper width, increase height;
  226.                 float t = i / (float)GrassSegments;
  227.                 float segmentHeight = _GrassHeight * t;
  228.                 float segmentWidth = _GrassWidth * (1 - t);
  229.  
  230.                 // the first (0) grass segment is thinner
  231.                 segmentWidth = i == 0 ? _GrassWidth * 0.3 : segmentWidth;
  232.  
  233.                 float segmentForward = pow(abs(t), _BladeCurve) * forward;
  234.  
  235.                 // Add below the line declaring float segmentWidth.
  236.                 float3x3 transformMatrix = i == 0 ? facingRotationMatrix : transformationMatrix;
  237.  
  238.                 // first grass (0) segment does not get displaced by interactivity
  239.                 float3 newPos = i == 0 ? v0 : v0 + ((float3(sphereDisp.x, sphereDisp.y, sphereDisp.z) + wind1) * t);
  240.  
  241.                 // every segment adds 2 new triangles
  242.                 triStream.Append(GrassVertex(newPos, segmentWidth, segmentHeight, offset, segmentForward, float2(0, t), transformMatrix, faceNormal, color));
  243.                 triStream.Append(GrassVertex(newPos, -segmentWidth, segmentHeight, offset, segmentForward, float2(1, t), transformMatrix, faceNormal, color));
  244.  
  245.  
  246.  
  247.             }
  248.             // Add just below the loop to insert the vertex at the tip of the blade.
  249.             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));
  250.             // restart the strip to start another grass blade
  251.             triStream.RestartStrip();
  252.         }
  253.     }
  254.  
  255.     ENDHLSL
  256.  
  257.         // color pass
  258.         SubShader
  259.     {
  260.         Tags{ "RenderType" = "Opaque" "RenderPipeline" = "UniversalRenderPipeline" }
  261.  
  262.         Cull Off
  263.         Pass
  264.     {
  265.  
  266.         HLSLPROGRAM
  267.  
  268.     float4 _TopColor;
  269.     float4 _BottomColor;
  270.     float _AmbientStrength;
  271.  
  272.     // The fragment shader definition.            
  273.     half4 frag(g2f i) : SV_Target
  274.     {
  275.         float4 shadowCoord = TransformWorldToShadowCoord(i.worldPos);
  276. #if _MAIN_LIGHT_SHADOWS
  277.     Light mainLight = GetMainLight(shadowCoord);
  278. #else
  279.     Light mainLight = GetMainLight();
  280. #endif
  281.     float shadow = mainLight.shadowAttenuation;
  282.  
  283.     // extra point lights support
  284.     float3 extraLights;
  285.     int pixelLightCount = GetAdditionalLightsCount();
  286.     for (int j = 0; j < pixelLightCount; ++j) {
  287.         Light light = GetAdditionalLight(j, i.worldPos, half4(1, 1, 1, 1));
  288.         float3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
  289.         extraLights += attenuatedLightColor;
  290.     }
  291.     float4 baseColor = lerp(_BottomColor, _TopColor, saturate(i.uv.y)) * float4(i.diffuseColor, 1);
  292.  
  293.     // multiply with lighting color
  294.     float4 litColor = (baseColor * float4(mainLight.color,1));
  295.  
  296.     litColor += float4(extraLights,1);
  297.     // multiply with vertex color, and shadows
  298.     float4 final = litColor * shadow;
  299.     // add in basecolor when lights turned down
  300.     final += saturate((1 - shadow) * baseColor * 0.2);
  301.     // fog
  302.     float fogFactor = i.fogFactor;
  303.  
  304.     // Mix the pixel color with fogColor.
  305.     final.rgb = MixFog(final.rgb, fogFactor);
  306.     // add in ambient color
  307.     final += (unity_AmbientSky * _AmbientStrength);
  308.    return final;
  309.    }
  310.        ENDHLSL
  311.    }
  312.         // shadow casting pass with empty fragment
  313.     Pass{
  314.         Name "ShadowCaster"
  315.         Tags{ "LightMode" = "ShadowCaster" }
  316.  
  317.         ZWrite On
  318.         ZTest LEqual
  319.  
  320.         HLSLPROGRAM
  321.  
  322.         #define SHADERPASS_SHADOWCASTER
  323.  
  324.         #pragma shader_feature_local _ DISTANCE_DETAIL
  325.  
  326.         half4 frag(g2f input) : SV_TARGET{
  327.             return 1;
  328.          }
  329.  
  330.         ENDHLSL
  331.         }
  332.     }
  333. }
  334.  
Advertisement
Add Comment
Please, Sign In to add comment