Advertisement
Guest User

GeometryGrassURP.shader

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