Carpet Rollup WPO Shader
Shader & Materials · UE 5.7
Was macht es
Ein animierter Rollup-Effekt für flache Meshes wie Teppiche oder Stoffe, komplett über einen Material-Shader mit World Position Offset gelöst. Ein einzelner Parameter RollAmount (0 bis 1) steuert, wie weit das Mesh aufgerollt ist. Die Mesh-Größe wird automatisch aus den Object Local Bounds ermittelt, sodass der Shader unabhängig von der konkreten Mesh-Dimension funktioniert.
Wie sieht es aus
Bilder einfügen
Warum habe ich das gebaut
Als Alternative zu klassischer Bone-Animation wollte ich eine Rollup-Bewegung rein im Vertex Shader realisieren. Vorteile: keine Skeletal Mesh Setup-Arbeit, vollständig GPU-basiert, instancing-fähig, parametrisch steuerbar per Timeline oder Sequencer. Zweiter Zweck war das Vertiefen meines HLSL-Verständnisses im Custom-Node-Kontext, nachdem ich bisher nur mit Material-Nodes gearbeitet hatte.
Wie funktioniert es (technisch)
Kernidee: Ein HLSL Custom Node berechnet pro Vertex, ob dieser bereits auf der Spirale liegt oder noch flach. Vertices hinter einer beweglichen Rolllinie werden auf eine Archimedische Spirale gemappt, deren Radius pro Umdrehung um die Teppichdicke wächst.
Mathematik: Bogenlänge der Spirale L(θ) = R·θ + 0.5·k·θ², wobei k = Thickness / 2π. Aus der bekannten Bogenlänge (Abstand des Vertex zur Rolllinie) wird per quadratischer Formel θ berechnet, daraus dann die finale Position als (r·sin θ, r·(1 − cos θ)).
Unreal-Features:
- Material Custom Node mit Float3 Output
- LocalPosition mit ExcludeOffsets als Eingabe
- Object Local Bounds (Min/Max) für automatische Längenermittlung
- TransformVector Node (Local → World) zwischen Custom Output und WPO, damit Actor-Rotation korrekt funktioniert
- Scalar Parameter für RollAmount, RollRadius, Thickness
- Blueprint mit Dynamic Material Instance und Timeline für Animation
Mesh-Anforderungen:
- Ausreichende Tesselation entlang der Rollachse (60+ Subdivisions für 3m Länge)
- Pivot am Mesh-Start, nicht in der Mitte
- Nanite deaktiviert oder explizit mit “Evaluate World Position Offset” konfiguriert
- Bounds Scale hochgesetzt (5-10), um Frustum-Culling zu vermeiden
Blender-Workflow:
- Plane mit Loop Cuts subdividen (nicht die UE-Default-Plane, die hat nur 4 Vertices)
- FBX Export mit angewandter Rotation und Skalierung
Was habe ich dabei gelernt
Viele einzelne Dinge, die beim nächsten Shader-Projekt direkt abrufbar sind:
- WPO erwartet World Space, nicht Local Space. Ohne TransformVector zwischen Custom Node und WPO funktionieren Rotationen nicht korrekt. Das war der am längsten übersehene Fehler.
- Nanite blockiert bestimmte WPO-Konstrukte stillschweigend. Simple Offsets gehen durch, bedingte Logik oft nicht. “Override Nanite Material → Evaluate World Position Offset” ist Pflicht, oder Nanite aus.
- Object Local Bounds machen Materials mesh-agnostisch. Das ist mein neuer Default-Ansatz für alle mesh-abhängigen Shader.
- Bounds Scale ist eine der häufigsten Ursachen für “Mesh verschwindet teilweise” bei WPO-Effekten.
- Tesselation bestimmt die Qualität des Effekts vollständig. WPO kann nur existierende Vertices verschieben. Die Standard-Plane mit 4 Vertices ist für keine WPO-Anwendung nutzbar.
- Debugging-Strategie: Custom Node Output parallel an Emissive Color hängen, um den Offset-Wert als Farbe sichtbar zu machen. Dazu der “Nuklear-Test” mit konstantem Offset, um WPO vs. Custom-Logik voneinander zu isolieren.
Was sind die Grenzen / offene Punkte
- Normals werden nicht rotiert. Die Beleuchtung auf der gekrümmten Rolle ist deshalb nicht korrekt. Für den Fix müsste im Custom Node eine Rotationsmatrix um die Quer-Achse auf die Vertex Normal angewendet werden.
- Bei vielen Umdrehungen (hohe RollAmount mit niedrigem RollRadius und hoher Thickness) überlappen sich die Schichten an der Unterseite der Rolle sichtbar. Der Effekt bleibt mathematisch korrekt, aber visuell unschön. Echter Self-Collision-Test wäre aufwendig und lohnt sich nicht.
- LOD-Verhalten: Bei weiter Entfernung degradiert der Effekt durch Mesh-LODs und WPO Disable Distance. Manuell auf 0 gesetzt für volle Qualität, ist aber eine Performance-Entscheidung.
- Shading mit Nanite wurde nicht abschließend getestet. Im aktuellen Projekt läuft Nanite aus.
Nächste Schritte (Ideen):
- Zweite Custom-Node-Output für rotierte Normal, um Beleuchtung zu fixen
- Variante mit zwei Rollrichtungen (von beiden Enden gleichzeitig)
- Parameter für Wobble/Ungleichmäßigkeit, damit die Rolle nicht mathematisch perfekt aussieht
- Test als Geometry Script für bake-to-static im Editor, falls Echtzeit nicht gebraucht wird
Assets / Dateien
- Projekt-Pfad:
/Projects/UE/CarpetRollup/ - Wichtige Assets:
M_CarpetRollup(Master Material mit Custom Node)BP_RollupCarpet(Actor mit Timeline und DMI)SM_CarpetPlane_Tessellated(vorbereitete Plane mit 60 Subdivisions)
- Source-Mesh: Blender-File in
/Source/Blender/carpet_plane.blend - Verwandte Projekte: noch keine, potenziell später Basis für Textil-Animationen allgemein