| name | pop-networks |
| description | MUST READ before building or editing POP networks, particle systems, GPU point/geometry work, glslPOP compute, or converting SOP chains to POPs in TouchDesigner 2025+. |
POP Networks
Build GPU-resident point and geometry systems with TouchDesigner POPs. POPs are the 2025+ point-operator family: geometry attributes live on the GPU, many operations run in parallel, and the right chain can replace CPU-heavy SOP or particle workflows.
Use this skill with /create-operator, /visual-aesthetics, performance.md, network-layout.md, and td-python.md. POP correctness is not just a clean network: it is a rendered frame, readable layout, bounded performance, and no operator errors.
POPs vs SOPs
Use POPs when the work is point-heavy, particle-heavy, or naturally parallel:
- Many points, particles, trails, instancing templates, or live geometry streams.
- GPU-side displacement, filtering, attributes, neighborhood queries, texture lookups, or simulation loops.
- Geometry that needs to stay GPU-resident for rendering, instancing, GLSL, or TOP/MAT interop.
- SOP chains whose main cost is moving or filtering lots of points every frame.
Keep SOPs when they are the honest tool:
- Booleans, UV unwrap, small static meshes, precise CPU geometry tools, or legacy SOP-only workflows.
- Tiny one-off static shapes where a SOP is clearer and has no measurable cost.
- Any workflow that needs a mature CPU operator with no POP equivalent.
Prefer POPs for dynamic scale, not as a religion. Start from the user's goal, expected point count, and render path, then choose the family that keeps the system understandable and fast.
Core Vocabulary
Generators create points or geometry:
gridPOP, boxPOP, spherePOP, torusPOP, tubePOP, circlePOP, linePOP, rectanglePOP.
randomPOP, sprinklePOP, pointgeneratorPOP, patternPOP, curvePOP.
particlePOP creates and manages built-in particles over time.
sourcePOP is common in feedback-style particle systems.
Filters and topology ops reshape or route data:
transformPOP, mathPOP, mathmixPOP, mathcombinePOP, normalizePOP, limitPOP, rerangePOP, quantizePOP, trigPOP.
noisePOP for built-in noise displacement or attribute generation.
attributePOP, attributecombinePOP, attributeconvertPOP, normalPOP.
mergePOP, switchPOP, selectPOP, deletePOP, groupPOP, sortPOP, copyPOP, blendPOP, nullPOP.
primitivePOP, convertPOP, extrudePOP, subdividePOP, facetPOP, polygonizePOP.
Spatial and simulation ops add interaction:
neighborPOP adds Nebr and NumNebrs for GPU spatial-neighbor logic.
proximityPOP, rayPOP, fieldPOP, lookuptexturePOP, lookupchannelPOP.
feedbackPOP loops frame-to-frame. Input 0 is the reset geometry; loopback from the output is automatic.
cachePOP, cacheblendPOP, cacheselectPOP, trailPOP, linemetricsPOP, skinPOP.
- Forces for particle workflows should start conservative: gravity around
0.1-0.2, damping around 0.98.
GLSL POPs are for work the built-ins cannot express cleanly:
glslPOP: default custom compute operator for one attribute class, multi-pass support.
glsladvancedPOP: use only when you need multi-class read/write, I[] index-buffer access, extra outputs, or custom output counts.
glslcopyPOP: copy source geometry many times with custom per-copy transforms.
glslcreatePOP, glslselectPOP for create/select patterns around GLSL outputs.
Converters bridge POPs to other families:
- Into POPs:
soptoPOP, choptoPOP, dattoPOP, toptoPOP, file/Alembic/point-file POPs.
- Out of POPs:
poptoCHOP, poptoDAT, glslmultiTOP, MAT attribute pages.
lookuptexturePOP samples TOPs from POP attributes. Set lookup attrs deliberately.
geometryCOMP Setup Ritual
For renderable POP geometry, build inside a geometryCOMP:
- Create the
geometryCOMP.
- Delete the auto-created torus immediately.
- Build the POP chain left-to-right and terminate in
null_out or another role-named nullPOP.
- Set display and render flags on the output
nullPOP.
- Add a material that can shade the points or geometry.
- Reference the MAT on the
geometryCOMP with a relative path such as ./pointsprite_particles.
- Render through a camera, light as needed, and a Render TOP.
Point rendering needs point primitives and a point-capable material:
- Points alone do not render. On generators, set Connectivity to create point primitives when you intend to render points.
- Use
pointspriteMAT for particle sprites, or a MAT that can read point/vertex attributes for the intended render style.
- The POP render color attribute is
Color as float4, not Cd. Cd is the SOP habit and will not do what you expect in POP render paths.
constantMAT can render point and primitive Color when point color application is enabled.
- Filled POP surfaces may be invisible from one side under backface culling. If that is not desired, set the MAT cull face to neither.
Attributes
Reserved/common attributes to recognize:
P float3 position, N float3 normal, T float4 tangent, Color float4 RGBA, Tex float3 texture coordinate.
PointScale, LineWidth, Weight.
- Particle attributes from
particlePOP: PartVel, PartId, PartAge, PartLifeSpan, PartDrag, PartMass, PartForce.
- Neighbor attributes from
neighborPOP: Nebr, NumNebrs.
Access components as P.x, P.y, P.z, Color.r, or with POP parameter component syntax such as P(0). Use dot notation in GLSL for readability.
Custom attributes must exist before downstream code writes them. Use attributePOP upstream or the Create Attributes sequence on the GLSL POP itself. In sequence parameters, set the block count first, then set names and types such as attr0name and attr0type.
Particle Lifecycle
For particlePOP and feedbackPOP, creation is not enough:
- Pulse
initializepulse to reset from the input geometry.
- Pulse
startpulse to begin playback.
- Use
play to pause or resume without resetting.
- Reinitialize after changing attribute schema, birth/life/capacity, or any upstream reset geometry that changes the expected state.
Particle capacity is a hard cap:
pointgeneratorPOP.numpoints is emission positions, not live particle count.
particlePOP.birthrate is births per second.
particlePOP.life is seconds each particle remains alive.
particlePOP.maxparticles must be at least birthrate x life, or particles are culled before their intended lifespan.
Start with modest counts and ramp only after measuring. Never default to millions.
GLSL POP Discipline
Use built-in POPs before custom GLSL when a short POP chain is clearer. lookuptexturePOP -> mathmixPOP is often better than a shader for texture lookup plus arithmetic.
For glslPOP:
- Write shader code in the auto-docked
<name>_compute DAT. Do not point at an unrelated text DAT.
- Read compile details from the docked
<name>_info DAT; the operator error may only say compile failed.
- List every written attribute in
outputattrs.
- Create custom output attributes first with the
attr sequence, for example attr0name and attr0type, or create them upstream with attributePOP.
- With default
outputaccess=writeonly, attributes listed in outputattrs that the shader does not write may be zeroed. Use readwrite when the shader must read output buffers, such as reading other points during a simulation.
- Guard indexes:
if (idx >= uint(P.length())) return;.
TDPerlinNoise() is not available in compute shaders. Use built-in noisePOP, a sampler input, or custom compute-safe noise.
- Uniforms are auto-declared by TD. Do not redeclare them in the shader; a redeclared uniform can produce a "Redeclaration" compile error.
- Use
vec uniform sequence entries for runtime values. const sequence entries recompile the shader when they change.
For glslcopyPOP:
- Input 0 is source geometry. Input 1 is template points when copy count should follow points.
- Write the point shader in the auto-docked
<name>_ptCompute DAT. Separate text DATs can compile while TDCopyIndex() stays wrong.
- Delete unused
_vertCompute and _primCompute docked DATs only if you are sure that build does not need them.
- Core functions include
TDCopyIndex(), TDTemplate_P(), TDTemplate_AttribName(), TDIn_P(), TDInputIndex(), and TDUpdatePointGroups().
For glsladvancedPOP:
- Use it only when
glslPOP cannot express the output class, topology, index buffer, or output-count requirements.
- Allocate output buffers explicitly. Point outputs need custom max points > 0; primitive/vertex/index outputs need custom max triangles > 0.
- Custom attributes need both Create Attribs and the matching output attributes parameter (
ptoutputattrs, primoutputattrs, or vertoutputattrs).
- In cache feedback patterns, use
cachePOP -> locked nullPOP to break cook dependency loops. Refresh with the unlock-cook-lock sequence: null.lock = False; null.cook(force=True); null.lock = True.
Conversion and Extraction
Use conversions deliberately because GPU -> CPU readback can stall:
poptoCHOP and poptoDAT download GPU data to CPU. Keep counts small or sample/debug only.
poptoCHOP channel names use attr_component, for example P_0, P_1, P_2.
lookuptexturePOP defaults can use world position components (P(0), P(1)) rather than UVs. Set lookup index attrs to Tex(0) and Tex(1) when sampling by UV.
- pbrMAT and phongMAT read
Tex as a vertex attribute, not a point attribute. Use attributeconvertPOP with point-to-vertex conversion for Tex; disable conflicting built-in vertex Tex on the source if needed.
normalPOP should set tangents to alwayscompute when using pbrMAT, or PBR lighting can fail.
Embody Workflow Gates
Performance is part of the build:
- Before any particle, feedback, GLSL, instancing, or large POP build, call
get_project_performance(include_hotspots=5) and record the baseline required by performance.md.
- Re-check after each significant step, not only at the end.
- Watch GPU headroom, frame time, dropped frames, hotspot cook time, and memory. Stop on the
performance.md thresholds.
- Start particle and instance counts modestly, then ramp with evidence. Do not default to millions.
Layout is part of the build:
- POP chains still follow the 200-unit grid and left-to-right signal flow.
glslPOP, glslcopyPOP, and other GLSL operators dock compute/info DATs. Place every docked DAT with the docked-DAT formula from network-layout.md.
execute_python creation drops POPs at (0, 0) unless you position them. A LAYOUT WARNING is a hard stop: query layout, move the ops, move docked DATs, and verify again.
- Every logical POP cluster gets an annotation enclosing its operators.
Naming is part of readability:
- Use
optype_name for processing ops: grid_points, noise_displace, glsl_sim, particle_emit, feedback_state, null_out.
- Name DATs by role, not type. Keep generated docked DAT names unless the operator requires them.
Verification is visual and structural:
- A POP render chain is verified by rendering it. Capture the Render TOP output with
capture_top and judge the frame using /visual-aesthetics.
- Let simulations settle before judging. Empty early frames can be lifecycle or demand issues, not final appearance.
- Verify animation over time with multiple captures when the POP chain is time-dependent.
- Run
get_op_errors with recurse=true after creating or modifying the network. Fix errors and warnings before claiming the build works.
Trap List
rectanglePOP size parameters are sizeu and sizev, not sizex or sizey. Setting sizex/sizey silently does nothing. General rule: verify live parameters with get_parameter before trusting type-level help or component names.
- The default torus inside a new
geometryCOMP will render if you leave it there. Delete it before building the POP chain -- this is the general geometryCOMP rule; see /create-operator -> "Geometry COMP: delete the default torus" for the render-flag detail.
- No display/render flags on the output
nullPOP means the render is empty.
- Points without point primitives do not render.
- POP render color is
Color (float4), not SOP-style Cd.
particlePOP and feedbackPOP need initializepulse -> startpulse -> play. Reinitialize after attribute changes or schema changes.
maxparticles < birthrate x life culls particles.
- Custom attributes must exist before GLSL writes them. Create them with the
attr sequence (attr0name, attr0type) or upstream attributePOP.
glslPOP writes to the docked compute DAT. Do not redeclare auto uniforms. Use vec for runtime values and avoid const for values that should animate without recompiling.
TDPerlinNoise() is not available in POP compute shaders.
normalPOP needs tangents set to alwayscompute for PBR lighting.
- pbrMAT reads vertex
Tex, not point Tex; convert with attributeconvertPOP.
mathmixPOP and mathcombinePOP sequences start empty. Set numBlocks before setting comb0oper, vec0*, or similar sequence parameters.
poptoCHOP outputs channels like P_0, P_1, P_2, not P.x.
Adapted from Derivative's TDMCPSkills (td-pop-family), with permission. Verify build-specific behavior against docs.derivative.ca.