With the comp's and the layer's motion-blur switches on, the renderer
hands effects the shutter (angle, phase, samples) — CC Particle World
now uses it: eight to sixty-four sprite fields sampled across the shutter
are averaged into the transfer, so fast particles draw the motion trails
After Effects shows instead of one sharp frozen field.
The GPU particle pass defers to the CPU while the shutter is open
(catalog::gpu_supported), keeping the oracle identical on both backends.
Tests: sim::particle_world_motion_blur_trails (blurred differs from
sharp, lights more pixels, keeps alpha energy) and a catalog assertion
for the CPU gate; effects 450 and gpu 212 lib tests pass; fmt and
clippy -D warnings clean.
The particles were composited with the original layer by the Transfer Mode, so the solid an
artist applies them to stayed visible. After Effects 2026 frames show no trace of it:
SceneYard "Burnout matchstick" (a red rectangle around the flame), "Documentary Man Falling"
(a black block over the light), "Task Preparation UI" (black solids under fireworks). The
Transfer Mode now only sets how the particles meet each other.
Mean abs error vs AE: Burnout matchstick 0.0191 -> 0.0130, Documentary Man Falling
0.1177 -> 0.0937 (Task Preparation also needs the next commit).
(cherry picked from commit 3eb3b9958f9cd929dcf060865e604d42cc0f9337)
(cherry picked from commit 729638710e63f4da10711fc5e6a1f7ddc42c37aa)
(cherry picked from commit 083332116c936f1b4863f0bb390d0647f2b567a1)
(cherry picked from commit 338421de36)
Cause: CC Particle World projected its particles through a fixed camera
(distance 2 layer widths, looking at the layer centre) and never asked the
host for the comp camera, so moving or orbiting a camera layer left the
particles flat on the layer. It also had no Extras > Effect Camera. Separately,
the layer cache key ignored the comp camera and lights, so the effects that
read them (Card Dance / Shatter / Card Wipe Comp Camera, First Comp Light,
Caustics) kept a stale frame when the camera, a light or the layer moved.
Fix: as the Cycore manual describes, Particle World sees its particles through
the comp's active camera layer when there is one (EffectHost::comp_scene now
says whether its camera is a camera layer's, CompScene::camera_layer), through
card3d's comp-camera projection (factored out of Card Dance as comp_proj, with
Proj::view for depth, size scale and screen velocity). Otherwise it uses the
new Extras > Effect Camera: Distance (2), Rotation X / Y / Z (0) and FOV (50)
orbit the world origin; FOV moves the camera so the origin's plane keeps the
scale Distance gives it, so the defaults reproduce the old fixed camera bit for
bit (golden hashes unchanged) and old projects render as before. The Effect
Camera is left out of the simulation cache key, so animating it doesn't
restart the simulation. The plan is shared, so the GPU compositor follows too.
The layer cache folds the comp scene into the key of layers running an effect
in effects::READS_COMP_SCENE (render::comp_scene is shared with the host).
Tests: sim particle_world_follows_the_comp_camera (panning a camera layer moves
the particles, zooming spreads them, the Effect Camera is ignored then, the
default view keeps the Effect Camera, cameras facing away / zero / NaN draw
nothing) and particle_world_effect_camera (missing params = defaults, rotation,
distance and FOV change the view, extremes stay finite, the sim key ignores the
camera); render particle_world_follows_the_comp_camera (a real camera layer
panned 40 px moves the particles left, and the cached render after the move
equals an uncached one: it failed with the old cache key); gpu
particle_world_through_the_comp_camera (CPU vs GPU at 8 / 32 bpc, full and
half resolution). particle_golden / sim_golden unchanged. effects.md
regenerated; parity.md and gaps.md describe the fix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GPU render passes for CC Particle World / Systems II, Particle Playground,
CC Ball Action, CC Pixel Polly, CC Scatterize and Curl Noise (fx_particles,
chunked multi-pass raster); Shatter wireframe views, Foam extras, Timewarp
with a Matte Layer, strong Warp Fisheye/Twist (CPU f64 inverse map) and
custom .ocio configs no longer fall back to the CPU. CPU refactors pinned by
particle_golden / timewarp_golden / sim_golden hashes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CC Rainfall, Snowfall, Star Burst, Bubbles, Drizzle, Hair, Mr. Mercury,
Caustics, Wave World, Foam, Shatter, Card Dance and Card Wipe render on the GPU
(fx_sim.rs / fx_sim.wgsl). The per-frame simulation / layout stays on the CPU
and is shared with the CPU effect through plans (effects::sprite_plan,
piece_plan, bubble_list, mercury_blobs, drizzle_drops, wave_world_plan,
caustics_setup); a tiled item rasteriser composites sprites, bubbles, blob
fields and textured pieces in the CPU's order and shading. Layer-dependent
sprite colours (refracting rain, star-burst and hair roots) are sampled per
pixel; piece plans read the frame back once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Closed-form weather/bubble/star effects; stepped particle, wave and foam sims through the
checkpointed SimCache (seek-consistent); band-bucketed sprite/piece rasteriser and textured
3D pieces via per-piece inverse homography.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>