Graphics API
Vulkan Grass Rendering
A real-time Vulkan grass renderer focused on procedural blade representation, dynamic force simulation, GPU-friendly culling, blade-count performance analysis, and tessellation-based level of detail.
Overview
This project renders a dense animated grass field in Vulkan. Each blade is modeled procedurally, simulated with physical and procedural forces, and optimized through multiple culling strategies to preserve real-time performance across large blade counts.
Feature 1
Grass Blade Representation
Bezier Curve Model
Each grass blade is represented as a quadratic Bezier curve with three control points: v0, v1, and v2. This gives every blade a compact procedural shape that can bend naturally.
Physical Properties
Each blade stores height, width, orientation, and a stiffness coefficient. These parameters control the blade's profile and how strongly it reacts to external forces.
Dynamic Simulation
Blades respond to gravity, recovery forces, and procedural wind in real time, creating field-scale motion without hand-authored animation.
Feature 2
Forces Simulation
Gravity Force
The simulation combines environmental downward gravity with front gravity based on blade orientation. Together, these forces create a natural drooping effect.
Recovery Force
Recovery force restores the blade toward its original upright position using the stiffness coefficient. Higher stiffness values recover faster and create more rigid grass.
Wind Force
Wind is generated from a multi-octave noise field with spatial variation and temporal animation. Blades bend more strongly when wind direction aligns with their orientation, and the effect is weighted so tips move more than roots.
Feature 3
Culling Optimizations
The renderer implements three culling strategies to reduce unnecessary blade rendering: orientation culling, view-frustum culling, and distance-based culling with LOD.
Orientation Culling
Culls blades nearly parallel to the view direction because they appear as thin lines from the camera perspective.
dot(bladeDirection, viewDirection) > 0.9
View-Frustum Culling
Tests the root, tip, and midpoint of each blade against the camera frustum and only renders blades visible on screen.
Distance Culling with LOD
Culls blades beyond the maximum distance and progressively reduces density for farther blades using bucketed distance ranges.
Performance
Blade Count Analysis
Performance was measured at a 1080 x 768 window size. The system maintains excellent performance above 1000 FPS up to 32,768 blades, drops to roughly 540 FPS at 131K blades, and remains practical on an RTX 3080 up to approximately 500K blades for playable real-time rendering.
Observed Trend
Performance degrades approximately linearly with blade count in log scale. Beyond one million blades, the workload becomes impractical for real-time applications.
Practical Range
The renderer can handle roughly 500K blades while maintaining playable framerates above 60 FPS on an RTX 3080.
Extra Credit
Tessellation-Based LOD
The renderer adjusts tessellation level dynamically based on distance to the camera. Nearby grass receives more segments for smooth silhouettes, while distant grass uses fewer vertices to reduce rendering cost.