Guest User

Grass.compute

a guest
Jul 16th, 2021
6,236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // @Minionsart version
  2. // credits  to  forkercat https://gist.github.com/junhaowww/fb6c030c17fe1e109a34f1c92571943f
  3. // and  NedMakesGames https://gist.github.com/NedMakesGames/3e67fabe49e2e3363a657ef8a6a09838
  4. // for the base setup for compute shaders
  5.  
  6. // Each #kernel tells which function to compile; you can have many kernels
  7. #pragma kernel Main
  8.  
  9.  
  10. // Define some constants
  11. #define PI          3.14159265358979323846
  12. #define TWO_PI      6.28318530717958647693
  13.  
  14. // This describes a vertex on the source mesh
  15. struct SourceVertex
  16. {
  17.     float3 positionOS; // position in object space
  18.     float3 normalOS;
  19.     float2 uv;  // contains widthMultiplier, heightMultiplier
  20.     float3 color;
  21. };
  22.  
  23. // Source buffers, arranged as a vertex buffer and index buffer
  24. StructuredBuffer<SourceVertex> _SourceVertices;
  25.  
  26. // This describes a vertex on the generated mesh
  27. struct DrawVertex
  28. {
  29.     float3 positionWS; // The position in world space
  30.     float2 uv;
  31.     float3 diffuseColor;
  32. };
  33.  
  34. // A triangle on the generated mesh
  35. struct DrawTriangle
  36. {
  37.     float3 normalOS;
  38.     DrawVertex vertices[3]; // The three points on the triangle
  39. };
  40.  
  41. // A buffer containing the generated mesh
  42. AppendStructuredBuffer<DrawTriangle> _DrawTriangles;
  43.  
  44. // The indirect draw call args, as described in the renderer script
  45. struct IndirectArgs
  46. {
  47.     uint numVerticesPerInstance;
  48.     uint numInstances;
  49.     uint startVertexIndex;
  50.     uint startInstanceIndex;
  51. };
  52.  
  53. // The kernel will count the number of vertices, so this must be RW enabled
  54. RWStructuredBuffer<IndirectArgs> _IndirectArgsBuffer;
  55.  
  56. // These values are bounded by limits in C# scripts,
  57. // because in the script we need to specify the buffer size
  58. #define GRASS_BLADES 4  // blade per vertex
  59. #define GRASS_SEGMENTS 5  // segments per blade
  60. #define GRASS_NUM_VERTICES_PER_BLADE (GRASS_SEGMENTS * 2 + 1)
  61.  
  62. // ----------------------------------------
  63.  
  64. // Variables set by the renderer
  65. int _NumSourceVertices;
  66.  
  67. // Local to world matrix
  68. float4x4 _LocalToWorld;
  69.  
  70. // Time
  71. float _Time;
  72.  
  73. // Grass
  74. half _GrassHeight;
  75. half _GrassWidth;
  76. float _GrassRandomHeight;
  77.  
  78. // Wind
  79. half _WindSpeed;
  80. float _WindStrength;
  81.  
  82. // Interactor
  83. half _InteractorRadius, _InteractorStrength;
  84.  
  85. // Blade
  86. half _BladeRadius;
  87. float _BladeForward;
  88. float _BladeCurve;
  89. int _MaxBladesPerVertex;
  90. int _MaxSegmentsPerBlade;
  91.  
  92. // Camera
  93. float _MinFadeDist, _MaxFadeDist;
  94.  
  95. // Uniforms
  96. uniform float3 _PositionMoving;
  97. uniform float3 _CameraPositionWS;
  98.  
  99.  
  100. // ----------------------------------------
  101.  
  102. // Helper Functions
  103.  
  104. float rand(float3 co)
  105. {
  106.     return frac(
  107.     sin(dot(co.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
  108. }
  109.  
  110. // A function to compute an rotation matrix which rotates a point
  111. // by angle radians around the given axis
  112. // By Keijiro Takahashi
  113. float3x3 AngleAxis3x3(float angle, float3 axis)
  114. {
  115.     float c, s;
  116.     sincos(angle, s, c);
  117.  
  118.     float t = 1 - c;
  119.     float x = axis.x;
  120.     float y = axis.y;
  121.     float z = axis.z;
  122.  
  123.     return float3x3(
  124.     t * x * x + c, t * x * y - s * z, t * x * z + s * y,
  125.     t * x * y + s * z, t * y * y + c, t * y * z - s * x,
  126.     t * x * z - s * y, t * y * z + s * x, t * z * z + c);
  127. }
  128.  
  129. // Generate each grass vertex for output triangles
  130. DrawVertex GrassVertex(float3 positionOS, float width, float height,
  131. float offset, float curve, float2 uv, float3x3 rotation, float3 color)
  132. {
  133.     DrawVertex output = (DrawVertex)0;
  134.    
  135.     float3 newPosOS = positionOS + mul(rotation, float3(width, height, curve) + float3(0, 0, offset));
  136.     output.positionWS = mul(_LocalToWorld, float4(newPosOS, 1)).xyz;
  137.     output.uv = uv;
  138.     output.diffuseColor = color;
  139.     // shadows is exactly as positionWS (no need to create a new variable)
  140.     return output;
  141. }
  142.  
  143. // ----------------------------------------
  144.  
  145. // The main kernel
  146. [numthreads(128, 1, 1)]
  147. void Main(uint3 id : SV_DispatchThreadID)
  148. {
  149.     // Return if every triangle has been processed
  150.     if ((int)id.x >= _NumSourceVertices)
  151.     {
  152.         return;
  153.     }
  154.    
  155.     SourceVertex sv = _SourceVertices[id.x];
  156.  
  157.     float forward =  _BladeForward;
  158.    
  159.     float3 perpendicularAngle = float3(0, 0, 1);
  160.     float3 faceNormal = cross(perpendicularAngle, sv.normalOS);  // multiply GetMainLight().direction in later stage
  161.  
  162.     float3 worldPos = mul(_LocalToWorld, float4(sv.positionOS, 1)).xyz;
  163.  
  164.     // Camera Distance for culling
  165.     float distanceFromCamera = distance(worldPos, _CameraPositionWS);
  166.     float distanceFade = 1 - saturate((distanceFromCamera - _MinFadeDist) / (_MaxFadeDist - _MinFadeDist));  // my version
  167.     // float distanceFade = 1 - saturate((distanceFromCamera - _MinFadeDist) / _MaxFadeDist);  // original
  168.  
  169.     // Wind
  170.     float3 v0 = sv.positionOS.xyz;
  171.     float3 wind1 = float3(
  172.     sin(_Time.x * _WindSpeed + v0.x) + sin(
  173.     _Time.x * _WindSpeed + v0.z * 2) + sin(
  174.     _Time.x * _WindSpeed * 0.1 + v0.x), 0,
  175.     cos(_Time.x * _WindSpeed + v0.x * 2) + cos(
  176.     _Time.x * _WindSpeed + v0.z));
  177.  
  178.     wind1 *= _WindStrength;
  179.  
  180.     // Interactivity
  181.     float3 dis = distance(_PositionMoving, worldPos);
  182.     float3 radius = 1 - saturate(dis / _InteractorRadius);
  183.     // in world radius based on objects interaction radius
  184.     float3 sphereDisp = worldPos - _PositionMoving; // position comparison
  185.     sphereDisp *= radius; // position multiplied by radius for falloff
  186.     // increase strength
  187.     sphereDisp = clamp(sphereDisp.xyz * _InteractorStrength, -0.8, 0.8);
  188.  
  189.     // Set vertex color
  190.     float3 color = sv.color;
  191.    
  192.     // Set grass height
  193.     _GrassWidth *= sv.uv.x;  // UV.x == width multiplier (set in GeometryGrassPainter.cs)
  194.     _GrassHeight *= sv.uv.y;  // UV.y == height multiplier (set in GeometryGrassPainter.cs)
  195.     _GrassHeight *= clamp(rand(sv.positionOS.xyz), 1 - _GrassRandomHeight,
  196.     1 + _GrassRandomHeight);
  197.  
  198.     // Blades & Segments
  199.     int numBladesPerVertex = min(GRASS_BLADES, max(1, _MaxBladesPerVertex));
  200.     int numSegmentsPerBlade = min(GRASS_SEGMENTS, max(1, _MaxSegmentsPerBlade));
  201.     int numTrianglesPerBlade = (numSegmentsPerBlade - 1) * 2 + 1;
  202.    
  203.     DrawVertex drawVertices[GRASS_NUM_VERTICES_PER_BLADE];
  204.  
  205.     for (int j = 0; j < numBladesPerVertex * distanceFade; ++j)
  206.     {
  207.         // set rotation and radius of the blades
  208.         float3x3 facingRotationMatrix = AngleAxis3x3(
  209.         rand(sv.positionOS.xyz) * TWO_PI + j, float3(0, 1, -0.1));
  210.         float3x3 transformationMatrix = facingRotationMatrix;
  211.         float bladeRadius = j / (float) numBladesPerVertex;
  212.         float offset = (1 - bladeRadius) * _BladeRadius;
  213.  
  214.         for (int i = 0; i < numSegmentsPerBlade; ++i)
  215.         {
  216.             // taper width, increase height
  217.             float t = i / (float) numSegmentsPerBlade;
  218.             float segmentHeight = _GrassHeight * t;
  219.             float segmentWidth = _GrassWidth * (1 - t);
  220.  
  221.             // the first (0) grass segment is thinner
  222.             segmentWidth = i == 0 ? _GrassWidth * 0.3 : segmentWidth;
  223.  
  224.             float segmentForward = pow(abs(t), _BladeCurve) * forward;
  225.  
  226.             // Add below the line declaring float segmentWidth
  227.             float3x3 transformMatrix = (i == 0) ? facingRotationMatrix: transformationMatrix;
  228.  
  229.             // First grass (0) segment does not get displaced by interactor
  230.             float3 newPos = (i == 0) ? v0 : v0 + (float3(sphereDisp.x, sphereDisp.y, sphereDisp.z) + wind1) * t;
  231.            
  232.             // Append First Vertex
  233.             drawVertices[i * 2] = GrassVertex(newPos, segmentWidth, segmentHeight, offset, segmentForward, float2(0, t), transformMatrix, color);
  234.  
  235.             // Append Second Vertex
  236.             drawVertices[i * 2 + 1] = GrassVertex(newPos, -segmentWidth, segmentHeight, offset, segmentForward, float2(1, t), transformMatrix, color);
  237.         }
  238.         // Append Top Vertex
  239.         float3 topPosOS = v0 + float3(sphereDisp.x * 1.2, sphereDisp.y, sphereDisp.z * 1.2) + wind1;
  240.         drawVertices[numSegmentsPerBlade * 2] = GrassVertex(topPosOS, 0, _GrassHeight, offset, forward, float2(0.5, 1), transformationMatrix, color);
  241.         // Append Triangles
  242.         for (int k = 0; k < numTrianglesPerBlade; ++k)
  243.         {
  244.             DrawTriangle tri = (DrawTriangle)0;
  245.             tri.normalOS = faceNormal;
  246.             tri.vertices[0] = drawVertices[k];
  247.             tri.vertices[1] = drawVertices[k + 1];
  248.             tri.vertices[2] = drawVertices[k + 2];
  249.             _DrawTriangles.Append(tri);
  250.         }
  251.        
  252.     }  // For loop - Blade
  253.    
  254.     // InterlockedAdd(a, b) adds b to a and stores the value in a. It is thread-safe
  255.     // This call counts the number of vertices, storing it in the indirect arguments
  256.     // This tells the renderer how many vertices are in the mesh in DrawProcedural
  257.     // InterlockedAdd(_IndirectArgsBuffer[0].numVerticesPerInstance, 3);
  258.     InterlockedAdd(_IndirectArgsBuffer[0].numVerticesPerInstance,
  259.     numTrianglesPerBlade * numBladesPerVertex * 3);
  260. }
Advertisement
Add Comment
Please, Sign In to add comment