Skip to content

Turn CHAOS destructibles (Geometry Collection assets) into very performant GPU simulated destructible static meshes driven by Niagara particles.

License

Notifications You must be signed in to change notification settings

eanticev/niagara-destruction-driver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Contributors Forks Stargazers Issues project_license LinkedIn


Logo

Niagara Destruction Driver

Turn CHAOS destructibles (Geometry Collection assets) into very performant GPU simulated destructible static meshes driven by Niagara particles.

Report Bug · Request Feature

About The Project

Product Name Screen Shot

This plugin allows you to take CHAOS destructibles (Geometry Collection assets) and process them into GPU simulated destructible static meshes driven by a Niagara Particle System. It's useful for creating cosmetic destructible props that are highly interactive but still very performant compared to CHAOS.

Under the hood the plugin uses a niagara system to simulate the physics of the fragments (bones) on the GPU, write their transforms to render targets, and finally a vertex shader to constrain the vertices of a specific fragment to its respective bone using the render targets. See more in Implementation Details below.

(back to top)

News

  • 2025/03/29 - Version 0.9.0 released.

(back to top)

Getting Started

This project was tested with UE 5.5.4.

Prerequisites

  • Unreal Engine Project with C++ enabled.
  • Recommended Engine Version 5.4 or above

Installation

  1. Drop the NiagaraDestructionDriver into your Game's /Plugins directory.
  2. Right click your uproject file and use "Generate Visual Studio Project files".
  3. Rebuild your project.

(back to top)

Usage

Using the plugin is hopefully pretty straightforward:

  • Create a CHAOS Geometry Collection from any static mesh in your project. (remember to use the TinyGEO tool to remove tiny geometry).
  • Add our custom MaterialFunction to any master shaders used in your static meshes.
  • Use the custom editor action to turn the Geometry Collection into a Niagara Destruction Driver blueprint.
  • Drop the blueprint in a level and the included function library in BP or C++ to intiate destruction force during gameplay.

Let's walk through it assuming you already have a CHAOS geometry collection:

STEP 1: On the master material you use for props that want to use with this plugin enable Use Material Attributes, and then add the MF_NiagaraDestructible Material Function and set it up with the NiagaraDestructionDriver_Enabled static switch as shown below:

STEP 2: Select a Geometry Collection in the editor. (NOTE: it should have only one level of geometry chunks due to current plugin limitations). Right Click and run Create Niagara Destruction Driver from the menu to generate the destruction driver blueprint and backing assets (destruction data asset, initial bone location texture, and the static mesh with custom UVs to drive the GPU simulation. More info in implementation details)

STEP 3: Drop the generated blueprint (subclass of ANiagaraDestructionDriverActor) into your level.

STEP 4: Add a Niagara Destruction Debugger (BP_DestructibleNiagaraRigDebugger) actor to your level. Simulate and drag around the debug actor to collide with the BP from step 2. to simulate "destruction force" on the actor.

(back to top)

Creating destruction force from your own gameplay

Call UNiagaraDestructionDriverHelper::InitiateDestructionForce in C++ or blueprint and provide the origin, radius, and force parameters.

const FVector WorldPosition = this->GetActorLocation();
const float Radius = 250.f;
const float Force = 1.0f;
UNiagaraDestructionDriverHelper::InitiateDestructionForce(WorldPosition, Radius, Force);

You can do the same from a blueprint:

initiating destruction force from blueprint

(back to top)

FAQ

  • Why do I need to add the material function? ... All of the destruction is driven by a shader vertex offset (WPO) so unfortunately you need to wire this up in the master prop material you plan to use in your game.
  • Why do I need the NiagaraDestructionDriver_Enabled static switch in my material? ... We don't need all the shader code to be active for all your props. This plugin generates Material Instance assets for the destructibles generated, and on those instances it sets the static switch to TRUE so the vertex shader code only runs for props that are processed by this plugin.
  • Is any of this replicated? ... No. For a poor man's solution just use and RPC and call InitiateDestructionForce on all clients/servers/etc.
  • Can I generate destructibles at runtime? ... No. The underlying engine code required to process the geometry collection is editor only.
  • Can you trace for collisions for the destroyed fragments? ... No. The fragments are animated using vertex offsets (WPO) in a shader. This system is intended for cosmetic destruction like wall surfaces and small props. In a future update we could allow this system to drive smaller chunks of a CPU driven chaos geometry collection where the larger chunks with collision etc. still work.
  • What's the point? Just use CHAOS destruction. ... Niagara driven destructibles are more performant.
  • Why did you make this? ... We developed a houdini driven prototype of this tech when I was CTO at Counterplay Games. Two very talented tech and VFX artists Milan Malata and James Sharpe (see acknowledgments) built that version. This is a clean room re-implementation of that system with a number of optimization and that does not require houdini.
  • I'm getting weird floating pieces in my destructibles? ... Make sure to use the TinyGEO tool in Chaos Fracture tools to merge tiny geometry to it's neighbors.

(back to top)

Available CVars

CVar Console Variable Value Notes
CVarNDD_DebugCollisions r.NDD.DebugCollisions [0 or 1] set this to 1 to show a debug sphere wherever InitiateDestructionForce is happening.
CVarNDD_DebugMaterial r.NDD.DebugMaterial [0 or 1] use debug materials that show bones + don't need special material integration.

(back to top)

Implementation Details

Runtime Architecture

architecture diagram

Expand for more implementation details

Runtime Notes

  • When using the destructible actor blueprint generated by this plugin, by default it shows proxy geometry (the static meshes used in the geometry collection) and hot swaps it for the destructible mesh with custom UVs only when destruction force actually overalps with this actor.
  • To prevent occlusion culling the destroyed fragments when the mesh leaves view, we hack the mesh bounds in the destructible actor using MeshComponent->SetBoundsScale(...)

Editor Asset Setup

editor setup diagram

Editor Utilities

The editor action that processes a Geometry Collection into all the relevant assets is implemented as one static function: UNiagaraDestructionDriverGeometryCollectionFunctions::GeometryCollectionToNiagaraDestructible and under the hood it does four things:

  1. UNiagaraDestructionDriverGeometryCollectionFunctions::GeometryCollectionToStaticMesh takes a geometry collection and generates a static mesh uasset with each vertex having a custom UV channel where the U value corresponds to the bone index that drives that vertex.
  2. UNiagaraDestructionDriverGeometryCollectionFunctions::SaveInitialBoneLocationsToTexture takes a geometry collection and generates a texture uasset where each pixel is the XYZ coord initial bone location for each of the bones of the geometry collection in local space. Since RGB can't be negative, the ALPHA value is a bitmask that encodes the sign (positive/negative) of each of the RGB coords.
  3. Creates a UNiagaraDestructionDriverDataAsset Data Asset that has references to all the generated assets in one convenient place.
  4. Creates a blueprint instance of ANiagaraDestructionDriverActor that has all the logic to wire niagara + the static mesh up. It references the created Data Asset as well as contains stand-in proxy geometry (the original static meshes that were used to set up the geometry collection) and hot-swaps them for the Niagara Driven Destructible mesh when destruction actually occurs.

For more info, please refer to the Documentation

(back to top)

Roadmap

  • Nanite support and testing.
  • Have the custom UV channel index be a parameter instead of defaulting to index 1 (current limitation)
  • Would be nice if PositionsTexture was DELTAs so it can be black / empty at resting state.
  • Deal with motion blur by finishing the motion vector implementation in the VAT material function (needs RTs for previous frame bone position/rotation).
  • Support for more than ONE level of chaos geometry collection.
  • Support for internal structure connectivity graph to avoid "floating" pieces.
  • Make the destructible actor and particle system movable.
  • Make sure that fragments are not culled when original mesh is out of vision bounds. (did a bit of work here with MeshComponent->SetBoundsScale)

See the open issues for a full list of proposed features (and known issues).

(back to top)

Contributing

Any contributions you make are greatly appreciated. If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

License

Distributed under the MIT License. See LICENSE for more information.

(back to top)

Contact

Emil Anticevic - @eanticev

Project Link: https://github.com/eanticev/niagara-destruction-driver

(back to top)

Acknowledgments

  • James Sharpe - x.com/_JamesSharpe_ - github.com/UnconsciousObserver - As the VFX Lead at Counterplay Games in 2023, James architected and implemented the original iteration of this approach.
  • Milan Malata - github.com/mimalata. As the Principal Technical Artist at Counterplay Games in 2023, Milan built the Houdini fracture and VAT texture generation workflows for the original HDA based iteration of this approach.
  • Alan Lee - As the technical art director at Counterplay Games, Alan put this system into production.
  • Joshua Carlos - As a Senior Technical Artist at Counterplay Games in 2023, Joshua handled building python workflows to execute the HDAs on 1000s of props. The CHAOS mesh uasset generator is inspired by his work.

(back to top)

About

Turn CHAOS destructibles (Geometry Collection assets) into very performant GPU simulated destructible static meshes driven by Niagara particles.

Topics

Resources

License

Stars

Watchers

Forks