Video summary
How I built a realistic grass shader in UE5! Shader driven bend, clump, tilt, wind and more!
Main summary
Key takeaways
Summary of Technological Concepts / Features (UE5 Grass Shader)
3-Part Series Context
- Video #2 builds on:
- Part 1: Blender + UE5/Unreal Engine setup, including:
- Niagara-driven 2D wind system
- Dynamic tiling wind textures
- Simple grass animation and projection tricks
- Notes that prior “industry-grade” grass techniques were discussed in an earlier related video.
- Part 1: Blender + UE5/Unreal Engine setup, including:
Goal
Create realistic, fluffy animated grass using primarily World Position Offset (WPO), with extensive control via:
- shader math
- texture-driven masks
- per-blade/per-card randomization
Grass Mesh + Data Setup (Blender)
Grass Mesh Uses Flat Undeformed Cards
- Cards are intentionally flat
- All cards are oriented toward the positive X-axis
- Uses UV map #1 for grass textures
Baked Per-Card Data (via Blender Add-on)
A “data baker” Blender addon is used to bake into UVs:
- Pivot/baked pivot data into UVs
- Normalized height baked into UV (vertical axis)
- Random value per card baked into UV (horizontal axis)
Vertex-Stored Random Direction
This workflow relies heavily on storing random per-card directions in:
- vertex normals
- vertex colors
So each grass card can be oriented differently without expensive per-pixel logic.
World Position Offset Reconstruction: Location, Scale, Rotation
Reconstruct World Position From Scratch
Uses a common WPO trick:
- subtract WorldPosition from 0 (collapsing vertices)
- then re-add:
- baked pivot offsets
- instance transforms (scale/rotation/position)
Distance-Based Instance Fading
- Uses PerInstanceFadeAmount for smooth card presence across distance.
Per-Instance Scale Control
- Assumes uniform instance scaling
- Extracts scale (e.g., from instance scale Z).
Rotation via 3×3 Matrix
Random rotation is performed by:
- building a local coordinate system per card
- applying a 3×3 rotation matrix
Landscape Alignment
- Card “up” / orientation can align to the landscape normal at each instance position.
- Requires cross products to build a stable basis.
- Includes handling for non-orthogonal vectors (orthogonalizing basis vectors to avoid deformation).
Tilt Clumps
- Tilt/clump shifting is implemented by modifying the “Z vector” basis using clump/tilt textures.
Clumping System (Custom “Clump Map” Tool)
Purpose
Generate a texture that drives clumps by pulling each card’s “Z vector” toward a local direction/point.
Tool: UE Editor Utility Widget
- Uses a render target + dynamic brush material
- Paints procedural clump textures
- Outputs a tileable static texture saved to the UE asset directory
Key Shader Logic in the Tool
- Brush uses radial direction from brush center in UV space
- Adds noise for organic flow
- Uses a mask (subtitled as a “billionaire sphere mask,” likely a sphere-mask concept) to fade effects near the center and avoid bad intersections
- Brush is drawn many times and made tileable via repeated/offset drawing
Shader Application
- Avoids unstable per-vertex sampling from absolute world space by sampling the clump map using:
- baked pivots in object space
- Clump texture coordinates are randomized using each card’s stored random 2D direction.
- Additional controls include:
- Lerp-driven position offset (clump influence over blade bending)
- A shared “Z vector” framework used for wind sampling and bending
Wind Interaction (Directional Modulation + Bending)
Wind Sampled from 2D Wind Texture
- Samples the 2D wind texture to build a wind velocity vector
Wind Direction Matching
- Normalized wind velocity is dotted with the card’s facing/forward direction.
- Grass cards act like flat “sails,” reacting more when aligned with wind direction.
Curvature Along Blade
- Uses stored top gradient/UV data
- Offsets are faded along blade length to create curvature rather than uniform bending
Rest Pose Bending (Mathematical Curve)
Mathematical “Bend Modifier”
- Applies a bend using sign + cosine-style math (similar to a bend modifier shown earlier)
- Mesh export is optimized because cards start aligned to X-axis, making bending predictable.
Wind Affects Rest Pose
- Wind magnitude reduces/modifies the bend amount so grass appears:
- more curved at rest
- straighter under stronger wind
Camera-Facing + Density Illusion (Billboard-like Without Classic Billboards)
Problem Tackled
- With WPO cards you may get vertex cost without enough pixel coverage
- Classic camera-facing billboards maximize coverage but can look overly “billboard-y”
Solution
- Build a matrix to rotate cards toward the camera before bending.
- Discusses transform space options:
- View-space (shadow pass mismatch from light POV)
- Camera-space (shadow stability, different behavior)
- Final fix addresses order-of-operations complexity:
- bending expects X-axis-aligned meshes
- camera-facing rotation must be composed carefully
- uses an adjustment: un-rotate the view vector via the inverse of card rotation so camera-facing remains correct after random rotation
Normal Reconstruction (Most Complex Part)
Why Normals Are Hard
- Multiple WPO operations distort geometry
- Transforming existing normals becomes messy.
Approach: Rebuild World-Space Normals From Scratch
- Reconstruct normals using:
- bend direction from WPO
- planar normal logic derived from the rebuilt framework
- Mentions “schools”:
- Stylized: often use consistent upward normals
- Realistic: may use two-sided foliage shading and correct normals
Testing Setup
- Uses a small debug mesh (four cards)
- Helps identify issues like wrong-way rotation for normals.
Wind/Tilt Influence on Normals
- Workaround:
- lerp the world normal toward tilt direction
- ensures lighting responds consistently regardless of forward/up normal selection.
Normal Map Remapping
- Since normal maps are usually tangent-space, remaps/swizzles them into the reconstructed world-space basis built from:
- bend orientation
- tilt direction
- rebuilt coordinate frame (via cross products)
Opacity, LODs, and “Fluffy” Edges
LOD and Dithering
- Uses dither LOD fading for smoother transitions.
Distance-Based Opacity via Mask
- Uses a custom desert mask opacity approach to achieve fluffy edges.
Mip-map Issues
- Packed textures may become too “mushy” at distance, causing unintended transparency.
Two Mitigation Methods
- Adjust mip generation / texture settings (e.g., ensuring values remain consistent across the mip chain).
- Manual mip editing:
- build custom mip chain layers in Photoshop
- export to DDS
- import while preserving mip levels.
Shadow-Pass Tricks (Advanced)
- Uses Shadow Pass Switch to alter behavior in the shadow pass:
- change card opacity to adjust perceived density and shadow coverage
- Notes potential tradeoffs:
- LOD transitions
- shadow stability
Pixel Depth Offset & Depth Illusion
Pixel Depth Offset
- Uses a per-card random value to push pixels away in camera space
- Creates a depth illusion and reduces flat-card artifacts
- Caveat:
- can cause self-shadowing artifacts with dynamic lighting
- It’s mitigated by fading via mip handling.
Performance Notes / Technology Choices
Vertex Cost Awareness
Highlights that performance depends on:
- keeping vertex count low
- aggressive LODs
- minimizing quad overdraw
Not Using Nanite or Virtual Shadow Maps
- WPO compatibility concerns with:
- Nanite
- Virtual Shadow Maps
- The goal is WPO-first grass on more “solid” classic meshes plus traditional shadow maps.
Project Availability + Tools Mentioned
- Project files available as Patreon tier 3.
- Tools available as Patreon tier 1:
- Landscape layer capture tool
- Clump map tool
- Mentions a third video soon:
- workflow for creating foliage assets in Blender
- an addon to facilitate it
Main Speakers / Sources
Main Speaker
- The YouTube creator (unnamed in subtitles) leading the UE5 grass shader build and demonstrating the tools.
Software/Engine Sources Referenced
- Epic (indirect references to grass workflows; also mentions Lumen / two-sided foliage shading considerations)
- Ghost of Tsushima (inspiration for grass rendering approach)
- Unreal Engine / UE5 material & shader nodes
- WPO
- PerInstanceFadeAmount
- ShadowPassSwitch
- etc.
- Niagara (from Part 1: wind system + tiling wind textures)
Rate this summary
Your feedback will help improve summaries.
Improve this summary
Reprocess with a stronger model when the summary feels incomplete or inaccurate.
Translate summary in another language
Ask questions to this video
Chat for follow-up questions, clarifications, and source-backed answers.