Guest User

URPGeometryGrass.shader

a guest
Feb 12th, 2021
852
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_fog  
  40.  
  41.         // The Core.hlsl file contains definitions of frequently used HLSL
  42.         // macros and functions, and also contains #include references to other
  43.         // HLSL files (for example, Common.hlsl, SpaceTransforms.hlsl, etc.).
  44. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"    
  45. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
  46. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
  47. #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
  48.  
  49.         // The structure definition defines which variables it contains.
  50.         // This example uses the Attributes structure as an input structure in
  51.         // the vertex shader.
  52.         struct Attributes
  53.     {
  54.         // The positionOS variable contains the vertex positions in object
  55.         // space.
  56.         float4 positionOS   : POSITION;
  57.         float3 normal :NORMAL;
  58.         float2 texcoord : TEXCOORD0;
  59.         float4 color : COLOR;
  60.     };
  61.  
  62.     struct v2g
  63.     {
  64.         float4 pos : SV_POSITION;
  65.         float3 norm : NORMAL;
  66.         float2 uv : TEXCOORD0;
  67.         float3 color : COLOR;
  68.  
  69.  
  70.     };
  71.  
  72.     half _GrassHeight;
  73.     half _GrassWidth;
  74.     half _WindSpeed;
  75.     float _WindStrength;
  76.     half _Radius, _Strength;
  77.     float _Rad;
  78.  
  79.     float _RandomHeight;
  80.     float _BladeForward;
  81.     float _BladeCurve;
  82.  
  83.     float _MinDist, _MaxDist;
  84.  
  85.     uniform float3 _PositionMoving;
  86.  
  87.     v2g vert(Attributes v)
  88.     {
  89.         float3 v0 = v.positionOS.xyz;
  90.  
  91.         v2g OUT;
  92.         OUT.pos = v.positionOS;
  93.         OUT.norm = v.normal;
  94.         OUT.uv = v.texcoord;
  95.         OUT.color = v.color;
  96.         return OUT;
  97.     }
  98.  
  99.     struct g2f
  100.     {
  101.         float4 pos : SV_POSITION;
  102.         float3 norm : NORMAL;
  103.         float2 uv : TEXCOORD0;
  104.         float3 diffuseColor : COLOR;
  105.         float3 worldPos : TEXCOORD3;
  106.         float3 shadows : TEXCOORD4;
  107.         float fogFactor : TEXCOORD5;
  108.  
  109.     };
  110.  
  111.     float rand(float3 co)
  112.     {
  113.         return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
  114.     }
  115.  
  116.     // Construct a rotation matrix that rotates around the provided axis, sourced from:
  117.     // https://gist.github.com/keijiro/ee439d5e7388f3aafc5296005c8c3f33
  118.     float3x3 AngleAxis3x3(float angle, float3 axis)
  119.     {
  120.         float c, s;
  121.         sincos(angle, s, c);
  122.  
  123.         float t = 1 - c;
  124.         float x = axis.x;
  125.         float y = axis.y;
  126.         float z = axis.z;
  127.  
  128.         return float3x3(
  129.             t * x * x + c, t * x * y - s * z, t * x * z + s * y,
  130.             t * x * y + s * z, t * y * y + c, t * y * z - s * x,
  131.             t * x * z - s * y, t * y * z + s * x, t * z * z + c
  132.             );
  133.     }
  134.  
  135.  
  136.     // per new grass vertex
  137.     g2f GrassVertex(float3 vertexPos, float width, float height, float offset, float curve, float2 uv, float3x3 rotation, float3 faceNormal, float3 color, float3 worldPos) {
  138.         g2f OUT;
  139.         OUT.pos = TransformObjectToHClip(vertexPos + mul(rotation, float3(width, height, curve) + float3(0, 0, offset)));
  140.         OUT.norm = faceNormal;
  141.         OUT.diffuseColor = color;
  142.         OUT.uv = uv;
  143.         OUT.shadows = TransformObjectToWorld(vertexPos + mul(rotation, float3(width, height, curve) + float3(0, 0, offset)));
  144.         OUT.worldPos = worldPos;
  145.         float fogFactor = ComputeFogFactor(OUT.pos.z);
  146.  
  147.         OUT.fogFactor = fogFactor;
  148.  
  149.  
  150.         return OUT;
  151.     }
  152.  
  153.     // wind and basic grassblade setup from https://roystan.net/articles/grass-shader.html
  154.     // limit for vertices
  155.     [maxvertexcount(48)]
  156.     void geom(point v2g IN[1], inout TriangleStream<g2f> triStream)
  157.     {
  158.  
  159.  
  160.  
  161.         float forward = rand(IN[0].pos.yyz) * _BladeForward;
  162.         Light mainLight = GetMainLight();
  163.  
  164.  
  165.         float3 lightPosition = mainLight.direction;
  166.  
  167.         float3 perpendicularAngle = float3(0, 0, 1);
  168.         float3 faceNormal = cross(perpendicularAngle, IN[0].norm) * lightPosition;
  169.  
  170.         float3 worldPos = TransformObjectToWorld(IN[0].pos);
  171.  
  172.         // camera distance for culling
  173.         float distanceFromCamera = distance(worldPos, _WorldSpaceCameraPos);
  174.         float distanceFade = 1 - saturate((distanceFromCamera - _MinDist) / _MaxDist);
  175.  
  176.         float3 v0 = IN[0].pos.xyz;
  177.  
  178.         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,
  179.             cos(_Time.x * _WindSpeed + v0.x * 2) + cos(_Time.x * _WindSpeed + v0.z));
  180.  
  181.         wind1 *= _WindStrength;
  182.  
  183.  
  184.         // Interactivity
  185.         float3 dis = distance(_PositionMoving, worldPos); // distance for radius
  186.         float3 radius = 1 - saturate(dis / _Radius); // in world radius based on objects interaction radius
  187.         float3 sphereDisp = worldPos - _PositionMoving; // position comparison
  188.         sphereDisp *= radius; // position multiplied by radius for falloff
  189.                               // increase strength
  190.         sphereDisp = clamp(sphereDisp.xyz * _Strength, -0.8, 0.8);
  191.  
  192.         // set vertex color
  193.         float3 color = (IN[0].color);
  194.         // set grass height
  195.         _GrassHeight *= IN[0].uv.y;
  196.         _GrassWidth *= IN[0].uv.x;
  197.         _GrassHeight *= clamp(rand(IN[0].pos.xyz), 1 - _RandomHeight, 1 + _RandomHeight);
  198.  
  199.         // grassblades geometry
  200.         for (int j = 0; j < (GrassBlades * distanceFade); j++)
  201.         {
  202.             // set rotation and radius of the blades
  203.             float3x3 facingRotationMatrix = AngleAxis3x3(rand(IN[0].pos.xyz) * TWO_PI + j, float3(0, 1, -0.1));
  204.             float3x3 transformationMatrix = facingRotationMatrix;
  205.             float radius = j / (float)GrassBlades;
  206.             float offset = (1 - radius) * _Rad;
  207.             for (int i = 0; i < GrassSegments; i++)
  208.             {
  209.                 // taper width, increase height;
  210.                 float t = i / (float)GrassSegments;
  211.                 float segmentHeight = _GrassHeight * t;
  212.                 float segmentWidth = _GrassWidth * (1 - t);
  213.  
  214.                 // the first (0) grass segment is thinner
  215.                 segmentWidth = i == 0 ? _GrassWidth * 0.3 : segmentWidth;
  216.  
  217.                 float segmentForward = pow(t, _BladeCurve) * forward;
  218.  
  219.                 // Add below the line declaring float segmentWidth.
  220.                 float3x3 transformMatrix = i == 0 ? facingRotationMatrix : transformationMatrix;
  221.  
  222.                 // first grass (0) segment does not get displaced by interactivity
  223.                 float3 newPos = i == 0 ? v0 : v0 + ((float3(sphereDisp.x, sphereDisp.y, sphereDisp.z) + wind1) * t);
  224.  
  225.                 // every segment adds 2 new triangles
  226.                 triStream.Append(GrassVertex(newPos, segmentWidth, segmentHeight, offset, segmentForward, float2(0, t), transformMatrix, faceNormal, color, worldPos));
  227.                 triStream.Append(GrassVertex(newPos, -segmentWidth, segmentHeight, offset, segmentForward, float2(1, t), transformMatrix, faceNormal, color, worldPos));
  228.  
  229.  
  230.  
  231.             }
  232.             // Add just below the loop to insert the vertex at the tip of the blade.
  233.             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));
  234.             // restart the strip to start another grass blade
  235.             triStream.RestartStrip();
  236.         }
  237.     }
  238.  
  239.     ENDHLSL
  240.  
  241.         // color pass
  242.         SubShader
  243.     {
  244.         Tags{ "RenderType" = "Opaque" "RenderPipeline" = "UniversalRenderPipeline" }
  245.  
  246.         Pass
  247.     {
  248.  
  249.         HLSLPROGRAM
  250.  
  251.     float4 _TopColor;
  252.     float4 _BottomColor;
  253.     float _AmbientStrength;
  254.  
  255.     // The fragment shader definition.            
  256.     half4 frag(g2f i) : SV_Target
  257.     {
  258.         float shadow = 0;
  259. #if SHADOWS_SCREEN
  260.     // Defining the color variable and returning it.
  261.     half4 shadowCoord = ComputeScreenPos(i.pos);
  262. #else
  263.         half4 shadowCoord = TransformWorldToShadowCoord(i.shadows);
  264. #endif
  265.         Light mainLight = GetMainLight(shadowCoord);
  266. #ifdef _MAIN_LIGHT_SHADOWS
  267.         shadow = mainLight.shadowAttenuation;
  268. #endif
  269.         float4 baseColor = lerp(_BottomColor, _TopColor, saturate(i.uv.y)) * float4(i.diffuseColor, 1);
  270.  
  271.         // multiply with lighting color
  272.         float4 litColor = (baseColor * float4(mainLight.color,1));
  273.         // multiply with vertex color, and shadows
  274.         float4 final = litColor * shadow;
  275.         // add in basecolor when lights turned down
  276.         final += saturate((1 - shadow) * baseColor * 0.2);
  277.         // fog
  278.         float fogFactor = i.fogFactor;
  279.  
  280.         // Mix the pixel color with fogColor.
  281.         final.rgb = MixFog(final.rgb, fogFactor);
  282.         // add in ambient color
  283.         final += (unity_AmbientSky * _AmbientStrength);
  284.     return final;
  285.     }
  286.         ENDHLSL
  287.     }
  288.         // shadow casting pass with empty fragment
  289.         Pass{
  290.             Name "ShadowCaster"
  291.             Tags{ "LightMode" = "ShadowCaster" }
  292.  
  293.             ZWrite On
  294.             ZTest LEqual
  295.  
  296.             HLSLPROGRAM
  297.  
  298.         #define SHADERPASS_SHADOWCASTER
  299.  
  300.         #pragma shader_feature_local _ DISTANCE_DETAIL
  301.  
  302.             half4 frag(g2f input) : SV_TARGET{
  303.             return 0;
  304.         }
  305.  
  306.         ENDHLSL
  307.         }
  308.     }
  309. }
Advertisement
Add Comment
Please, Sign In to add comment