Canopy Flow - Realistic Wind for Skinned foliage

NOTE: I’ll be using this thread to post progress updates, new features, performance changes, roadmap notes, and major development updates going forward. Stay Tuned!


This started as a small experiment. I was messing around with skinned meshes and wanted to see how far I could push bone driven tree animations on Roblox. After watching a lot of foliage showcases, especially UE5 examples and a few Roblox ones like Fluorlite’s work, I wanted to see if I could get that same feeling of physical branches bending, leaves reacting, and wind movement flowing through the whole tree.

I posted a small showcase on Twitter, and the responses made me realize this could become something bigger than a cool little test. So I started turning it into a real tool, something that could be used in production of realistic projects.

Here is the link if you want to check it out: Elite on X: "Roblox Skinned Tree Wind Test #RobloxDev #ROBLOX" / X
calmbreezegif

Canopy Flow is a plugin and runtime wind system in development for skinned trees and foliage in Roblox. It animates the mesh’s bones, allowing the trunk, branches, and leaves to sway together.


Current Features

As of 10/9/2026, The runtime currently supports:

  • Bone driven trunk, branch, and leaf sway for skinned foliage
  • Client side visual wind animation
  • Adjustable wind strength, speed, gust motion, and bend limits
  • Wind direction controlled through plugin controls
  • Tree registration through CollectionService
  • Distance based animation culling and fading
  • Adjustable batching with a suggested starting batch size
  • Rig validation and support for fixed and custom bone layouts
  • Wind profiles for grouping trees with different settings
  • Calm, Breezy, and Storm presets
  • Viewport preview of supported trees
  • Metrics for wind-loop timing, batch activity, and bone updates

The goal is to make natural looking foliage movement easy to set up and tune while keeping the runtime lightweight.


Planned Features Currently

As of 10/9/2026, the main focus is on expanding wind control, improving large-scene handling, and making the system easier to integrate into different environments.

Planned work includes:

  • Adaptive batching TBD: adjusting the update workload based on measured runtime cost.

  • Frustum culling TBD: reducing animation updates for trees outside the camera view, with testing for visible shadows and transitions when trees return to view.
    Frustum Streaming: Stream What Your Players See (Testing Needed with the recent update)

  • Bone detail LOD TBD: reducing branch and leaf animation detail at greater distances while retaining simpler trunk motion. (Could potentially allow more trees to animate across a wider range within the same performance budget.)

  • Spatial partitioning TBD: grouping trees into regions to prioritize nearby checks. (If larger-scene testing shows a worthwhile performance benefit.)

  • Additional foliage support: extendingsetup guidance and testing to plants and ground foliage.

  • Custom wind presets: create, name, and save your own wind settings to reuse across trees and profiles.

  • Built-in foliage library: ready-to-use skinned trees, with included assets and redistribution permissions finalized before release.

  • Streaming improvements: further testing of partial rigs, trees loading and unloading, and registration recovery.

  • Regional wind zones Low Priority: different wind behavior for separate areas or biomes.

  • Expanded gust behavior Low Priority: more variation and control beyond the current repeating gust motion.

The planned foliage library is intended to provide ready skinned trees, helping developers get started without rigging every asset themselves.

I’ll post dated updates as features move through development, testing, and completion.


Performance

Keeping runtime work manageable has been a main development goal, since foliage animation and rendering can become expensive as scenes grow.

These are previously reported results from an earlier development test. They should not be treated as benchmarks for the current version.

Test Conditions

  • Approximately 225 tagged trees
  • Roblox client with graphics quality set to 10

Test System

  • NVIDIA RTX 4060
  • AMD Ryzen 5 5500
  • 32 GB DDR4 RAM
Metric Reported value
Total tagged trees Approximately 225
Bone transforms updated per frame under the test settings Approximately 144
Average exclusive time for the measured wind scope 0.43 ms
Peak exclusive time in the capture 0.56 ms
Exclusive scope time relative to a 60 FPS frame budget Approximately 2.6–3.4%
Reported wind-script memory / LuaHeap contribution Approximately 0.56 MB

The tagged tree count describes the scene population. Because updates are batched and distance based it should not be read as 225 trees receiving bone updates every frame.

Exclusive time excludes nested profiling scopes. These figures do not establish the complete cost of animated foliage, including downstream engine, rendering, and shadow work.

At 60 FPS, a frame lasts approximately 16.67 ms. The percentage above compares the reported exclusive scope timings with that duration; it is not the percentage used by the entire system.

The memory figure describes the reported script/LuaHeap contribution. It does not include all meshes, textures, engine allocations, or GPU resources.


Roadmap

Canopy Flow is still in development, so my focus is refining the runtime and plugin workflow while testing the remaining features.

Summary
  1. Refine the current runtime wind system
    Continue improving trunk, branch, and leaf motion while keeping the setup manageable.
  2. Improve existing features and fix edge cases
    Address bugs, unusual rigs, and anything that behaves inconsistently during testing.
  3. Continue testing streaming support
    Improve tree registration, loading, unloading, and recovery. Test compatibility with Roblox’s recently released Frustum Streaming.
  4. Update benchmarks and evaluate runtime optimizations
    Profile the current build in larger scenes and on different devices. Test adaptive batching, bone detail LOD, and animation frustum culling. Spatial partitioning remains under consideration pending further testing.
  5. Add more variation to the wind motion
    Expand gust and foliage movement controls while keeping rigging and tuning straightforward.
  6. Improve the overall plugin workflow
    Refine the existing installer, rig validation, wind controls, profiles, presets, and preview tools based on testing and feedback.
  7. Prepare the foliage library and setup guide
    Finalize ready-to-use skinned foliage, verify redistribution permissions, and document supported rigs and setup practices.
  8. Test with more developers and larger scenes before release
    Gather feedback across different environments and devices to identify performance, reliability, and usability issues.
  9. Release once the runtime and workflow are ready (NO RELEASE DATE YET)
    Release after testing shows that the core runtime and plugin tools are reliable enough for other developers to use.

The main goal is to make Canopy Flow useful for developers building larger outdoor environments with skinned foliage, while keeping setup and tuning straightforward.


Feedback Wanted

I’d love feedback from developers working with skinned foliage or outdoor environments. Let me know what you think of the movement, what would make setup easier, and what you’d like to see as development continues.

25 Likes

Working on a dedicated showcase an optimized forest environment running Canopy Flow with real shadows and tuned foliage. Dropping it in a separate post soon. First proper look at the plugin in a real scene soon!

1 Like
1 Like

where is a testable place to check it out?

I’ll add it in the post as well

this looks rly cool, i’d def try this out later on

1 Like

6/23/2026 Update:

Did some more research on algorithm based optimization for CanopyFlow. I think this is probably the better direction before jumping into something like Parallel Luau.

Algorithm optimization means improving how the system decides what trees and bones should update, instead of just trying to make the same amount of work run faster.


Frustum culling
Working on this atm along with the foliage/tree library. This would add a camera view visibility check before a tree enters the wind update path. Even if a tree is inside MaxDistance, it could be skipped if its bounds are outside the camera frustum. This would reduce unnecessary Bone.Transform updates for trees that are close but not visible on screen.

Adaptive batching
Still working on this. The current system uses a fixed TreesPerFrame batch size, but adaptive batching would adjust that value dynamically based on measured frame cost. If wind update time rises too high, the runtime could lower the batch size to reduce spikes. If performance stays low cost, it could increase the batch size for smoother update cycles.


LOD wind
Future feature. The system already fades wind strength based on distance using values like MaxDistance, FadeIn, FadeOut, and an internal tree.weight, so far trees gradually move less instead of instantly stopping.

LOD wind would build on top of that by also changing which bones are being updated at different distances. For example, nearby trees could get the full animation, including trunk, branches, and leaf motion. At mid range, the smaller leaf and branch motion could smoothly fade out first while the trunk keeps moving. At far range, only the trunk might keep a very subtle sway, or the tree could fully sleep once it is too far to notice.

The important part is that this would not snap on and off. The branch and leaf motion would fade down smoothly before those bones stop updating, so the tree does not suddenly change shape. This would let close trees keep high quality motion while far trees become much cheaper to animate.


Made in Mermaid Chart


Spatial partitioning
Future feature. Instead of treating every tree as one big flat list, trees could be grouped into world chunks or grid cells. Then the system only needs to check nearby chunks.

Theoretical Performance Estimate

These are rough estimates, and could still be wrong. Current testing with 200+ trees already shows the wind script staying fairly cheap, so smaller scenes may not see dramatic gains from every optimization. Most of these ideas matter more as tree counts scale into the thousands.

Current 200+ tree test

  • LOD wind: maybe around 5-15% script side improvement
    This would reduce how many branch/leaf bones keep updating at farther distances.

  • Adaptive batching: It’s mostly stability and not speed
    This would help keep frame cost controlled by lowering or raising the batch size based on runtime performance.

  • Frustum culling: around 5-20%, depending on camera view
    This would skip trees outside the camera view instead of only relying on distance.

  • Spatial partitioning: probably small at this scale
    With only a few hundred trees, the current flat list approach is already fine.

  • Custom rig optimization: around 5-20%, depending on bone count
    This would matter more for trees with higher bone counts or heavier branch setups.

Larger forest estimate

For forests with around 1,000-5,000+ tagged trees, these systems become more important.

  • LOD wind: around 20-50% less bone update work
    Nearby trees keep full motion, while far trees reduce to trunk-only or sleep.

  • Adaptive batching: prevents spikes and keeps frame cost controlled
    The system can adjust the workload instead of pushing too many trees in one frame.

  • Frustum culling: around 20-60% less active update work, depending on view direction
    Dense forests benefit more when many trees are behind or outside the camera view.

  • Spatial partitioning: major improvement for search/check overhead
    The runtime can focus on nearby world chunks instead of treating the whole forest as one giant list.

thanks for the testing place editable?

Video Showcase of different trees and adjust parameters.


Next showcase will feature Completed Plugin UI which will take a atleast a week for me bc of my schedule atm, Stay Tuned!

1 Like

How do you make the tree models? I think they look great

Thanks! I Made them in speedtree, trunk texture and atlas from textures.com modified them a bit in photoshop

The dead branchs at the bottom of the tree got messed up when I imported in studio bc of the rig, just decided to delete them and do the quick showcase vid above here, working on more opitmization on this as this will be included in the plugin library.

10/9/2026 Update:

Quick clarification, as of today the current runtime uses adjustable fixed batching and fades trees as they enter or leave the animation range. Adaptive batching, animation frustum culling, and bone detail LOD are still planned. Spatial partitioning is under consideration but I need to do more larger scene tests.

Smaller batches reduce per frame work but also reduce update frequency. Roblox’s newer Frustum Streaming is separate from animation culling, and I’ve yet to test if there are any issues with compatibility. The planned LOD transitions and performance benefits still need to be tested.

10/10/2026 Update:

More foliage! This pine set took me 6ish hours to make, including rigging.

Testing it in Studio revealed a few issues with the bend limit setting and current wind presets. I’ve added them to my current list. Once those are sorted out I’m gonna work on letting you create and save your own wind presets. It’s now in the planned features list.

Blender viewport Render:

Video: just messing with current lighting settings cleaning up setup in studio

:sob: Alright I got a bit ahead of myself with those %'s. The optimization ideas still make sense, but the gains need actual testing. More tagged trees doesn’t automatically mean more work per frame with the current batching, and the benefits overlap, so those estimates shouldn’t be added together.