# Changelog (/docs/changelog) Placeholder entries — version numbers and dates are illustrative until the first public builds ship. Subscribe from your [dashboard](/dashboard) to get release notes by email. ## 2026.2.0 — upcoming [#202620--upcoming] **Photon RTXPT** * DLSS Ray Reconstruction preset ladder replaces the single denoiser toggle * AOV layers: direct/indirect split output for external compositing * Fix: accumulation reset flashing under time-sliced material exports **Matter** * `Deterministic` mode — bit-identical replays at \~15% cost * Cloth self-collision robustness pass at high substep counts **Aura** * Input 4 normal-map support graduates from experimental * Fix: temporal ghosting on hard cuts with `Reset History` pulse ## 2026.1.1 [#202611] **All plugins** * Signed headless license tool (`nops-license.exe`) ships in the plugin folder — see [Licensing a render farm](/docs/guides/render-farm-licensing) * Status readout now reports the minimum driver version on refusal **Photon OVRTX** * Radiance cache probe refit no longer stalls on large geometry edits ## 2026.1.0 — first early-access builds [#202610--first-early-access-builds] * Photon RTXPT, Photon OVRTX, Matter, and Aura enter early access * Per-seat licensing with online and offline activation * TouchDesigner 2023.12000+ / driver 560+ floors established # Introduction (/docs) These pages are placeholder content while the plugins are in early access — the structure is real, the numbers are not final. Join the [waitlist](/) to be notified when they ship. ## What is NativeOps? [#what-is-nativeops] Every NativeOps plugin is a **native operator**: it registers itself with TouchDesigner like a built-in, cooks on the GPU, and shows up in the OP Create dialog next to everything else. No Python glue, no texture round-trips, no external processes to babysit. Written in C++/CUDA against TouchDesigner's plugin API. Zero-copy texture sharing means frames never leave the GPU on their way through your network. One license per machine, managed from your dashboard. Activation takes a key, not a hardware dongle — and moves with you when you swap workstations. ## The plugins [#the-plugins] Real-time path tracing inside TouchDesigner, built on NVIDIA's RTX Path Tracing SDK. The Photon front end on the ovrtx backend — the same scene semantics, tuned for interactive previz. GPU rigid bodies, fluids, and cloth as one operator suite — eight operators, one solver clock. Real-time 2D global illumination for layered scenes — emitters, occluders, and bounce in a single TOP. ## Quick start [#quick-start] ### Buy a license [#buy-a-license] Every plugin is sold per seat from the [products page](/products). The license key lands in your [dashboard](/dashboard) the moment checkout completes. ### Install the plugin [#install-the-plugin] Drop the plugin folder into TouchDesigner's plugin path and restart. [Installation](/docs/getting-started/installation) walks through both the per-user and system-wide paths. ### Activate your seat [#activate-your-seat] Paste your key into the operator's Activate parameter page — or activate offline for air-gapped machines. [Activation](/docs/getting-started/activation) covers both. ## Why native operators? [#why-native-operators] Script TOPs and CHOPs run on the CPU, once per cook, with the GIL in the way. A path tracer or a fluid solver needs thousands of GPU dispatches per frame — that only works as a compiled plugin sharing TouchDesigner's own GPU context. Running a renderer in a separate process means every frame crosses process boundaries twice. A native operator cooks inside TouchDesigner's frame loop — the output TOP is the renderer's actual target texture. Parameters, exports, CHOP references, time-slicing — the things that make TouchDesigner TouchDesigner — only reach operators. NativeOps plugins expose everything as ordinary parameters, so your existing control rigs just work. ## Reading these docs as an agent [#reading-these-docs-as-an-agent] Append `.md` to any page URL for its raw markdown. [/llms.txt](/llms.txt) is the index, [/llms-full.txt](/llms-full.txt) is every page in one document, and the **Copy page** button up top yields the same markdown. # Overview (/docs/aura) **Aura** lights 2D scenes the way a renderer lights 3D ones. Feed it layers — who emits, who blocks — and it returns the scene with light that bounces, bleeds, and wraps. Motion graphics stop looking flat without leaving TOPs. Aura is the entry point to the NativeOps line: it runs on any CUDA-capable GPU from the 16-series up, no RT cores required. ## The idea [#the-idea] A 2D scene has the same light problems as a 3D one — a neon sign should tint the wall behind it; a character crossing a doorway should catch light from it. Aura solves radiance in screen space over your layers: * **Emitters** — any layer's bright pixels cast light, in nits * **Occluders** — alpha or a dedicated mask blocks and shadows * **Bounce** — one to four bounces of colored indirect light * **Volumetrics** — optional fog pass so beams read in empty space ## Where it sits in a network [#where-it-sits-in-a-network] ```text title="Typical chain" comp_layers (TOP) ──► aura1 (TOP) ──► bloom / grade ──► out ``` One Aura TOP per scene, after compositing and before grade — the same slot a lighting pass occupies in a 3D pipeline. [Inputs](/docs/aura/inputs) covers the layer contract. ## Next steps [#next-steps] The layer contract — what each input plug expects. Bounce counts, distance fields, quality ladders. # Inputs (/docs/aura/inputs) Aura takes up to four TOP inputs. Only the first is required — each one added unlocks a feature tier. | Input | Content | Unlocks | | --------------------- | ------------------------------------- | -------------------------------- | | 1 — Scene | Your composited layers, premultiplied | Emission from bright pixels | | 2 — Occlusion | Grayscale blocker mask | Shadows independent of alpha | | 3 — Emission override | RGB emission map, in nits | Emitters that aren't visible | | 4 — Normal | 2D normal map | Directional response on surfaces | ## The one rule: premultiplied alpha [#the-one-rule-premultiplied-alpha] Aura derives occlusion from input 1's alpha when no input 2 is wired. Straight (unpremultiplied) sources read as glowing halos around every edge. If halos appear around composited elements, the source is straight alpha — drop a Premultiply TOP in front, or wire a real occlusion mask into input 2. ## Emission without visibility [#emission-without-visibility] Input 3 answers the common request "light from off-screen": paint emitters into the override map and they cast without being drawn. ```python title="Flicker an off-screen fire" # noise TOP → level TOP (drives intensity) → input 3 op('aura1').par.emissionscale.expr = "1.0 + op('noise_fire')['chan1'] * 0.4" ``` Normal maps (input 4) are the cheapest large upgrade: characters rendered from a 3D DCC with a normal AOV pick up directional 2D light that tracks their forms — the flat-sticker look disappears. # Parameter reference (/docs/aura/parameters) Generated reference, same pipeline as the other plugins. Placeholder subset below. ## Light page [#light-page] ## Quality page [#quality-page] `Temporal Blend` above 0.9 ghosts on hard cuts. Pulse the `Reset History` parameter from your cue system on every scene change — one line in a Script CHOP callback. # Activation (/docs/getting-started/activation) Activation binds a seat from your [dashboard](/dashboard) to the current machine. Until then the operator runs in watermark mode — full function, watermarked output. ## Online activation [#online-activation] ### Open the Activate page [#open-the-activate-page] Every NativeOps operator has an **Activate** parameter page. Select the operator and switch to it. ### Paste your key [#paste-your-key] Keys look like `NOP-1C285B2D-6CE6-4BC7-B8BE-ADB6A7E304DA` and are listed in the [dashboard](/dashboard). Pulse **Activate**. ### Confirm the status [#confirm-the-status] The `Status` readout flips to `Licensed` and the watermark disappears on the next cook. The seat now shows this machine's name in your dashboard. Activation is once per machine, not per project — every `.toe` on the machine sees the seat. ## Offline activation [#offline-activation] For machines that never touch the internet: Pulse **Request Offline File** on the Activate page. The operator writes a `machine.request` fingerprint file next to the project. On any online machine, upload the request in the [dashboard](/dashboard) under **Seats → Offline activation**. It returns a signed `seat.license` file. Copy `seat.license` into the plugin folder on the offline machine and restart TouchDesigner. The fingerprint covers the GPU and motherboard. Swapping either invalidates an offline seat — deactivate from the dashboard first if hardware work is planned. ## Deactivating [#deactivating] Deactivate from the operator's Activate page (pulse **Deactivate**), or from the [dashboard](/dashboard) when the machine is gone — dead SSD, returned rental, stolen laptop. Dashboard deactivation is immediate and frees the seat for the next machine. Something stuck? [Troubleshooting → Activation problems](/docs/troubleshooting/activation-problems) covers the failure modes we know about. # Installation (/docs/getting-started/installation) Each plugin ships as a single folder containing the operator DLL and its resource files. TouchDesigner discovers it on startup — there is no installer and nothing touches the registry. Downloads are signed and versioned per TouchDesigner build line. Grab the build matching your TouchDesigner version from the [dashboard](/dashboard) — a `2025.30000` plugin will refuse to load in a `2023.12000` session. ## Install locations [#install-locations] Drop the plugin folder into your user plugin path. TouchDesigner scans it on every launch, and updates don't need admin rights. ```text title="Windows" %USERPROFILE%/Documents/Derivative/Plugins/PhotonRTXPT/ ``` For lab machines and render nodes where every user shares one install: ```text title="Windows (requires admin)" C:/Program Files/Derivative/TouchDesigner/Plugins/PhotonRTXPT/ ``` Ship the plugin inside a project folder for fully portable setups — the path is scanned relative to the `.toe` file: ```text title="Relative to your .toe" ./Plugins/PhotonRTXPT/ ``` Project-local plugins still need an activated seat on the machine that opens the project. Bundling the DLL does not bundle the license. ## What lands on disk [#what-lands-on-disk] ## Verify the install [#verify-the-install] Restart TouchDesigner. Plugins are scanned once at startup — a running session will not pick up a new folder. Open the OP Create dialog (double-click the network background). The operator appears under the **Custom** tab — `Photon RTXPT` in this example. Drop the operator into a network. Until a seat is activated it cooks in watermark mode — full function, watermarked output. Continue to [Activation](/docs/getting-started/activation). Developing on a laptop and deploying to a media server? Install per-user on the laptop and system-wide on the server — the license seat follows the machine, not the install location. # Licensing (/docs/getting-started/licensing) A **seat** is one plugin activated on one machine. Licenses are sold per plugin, per seat, with updates included for the duration of the license term. ## The model [#the-model] * **Per machine, not per user.** Any user account on an activated machine can use the plugin. Two workstations need two seats. * **Floating by deactivation.** Moving to a new machine is deactivate-then-activate from the [dashboard](/dashboard) — no support ticket required. * **Watermark mode is not a trial clock.** An unactivated operator never expires; it cooks full-rate with a watermark. Evaluate as long as you like. Render nodes cook headless with the same seat type — there is no separate render license. If a machine opens the `.toe`, it needs a seat. ## What a key looks like [#what-a-key-looks-like] ```text NOP-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX NOP-1C285B2D-6CE6-4BC7-B8BE-ADB6A7E304DA ``` The `NOP-` prefix, then a UUID — 32 hex characters, uppercase, in the usual 8-4-4-4-12 grouping. Case and hyphens are part of the key. Keys are plugin-scoped: a Photon RTXPT key will not activate Matter. Every key you own is listed in the [dashboard](/dashboard) with its activation state and the machine it's bound to. ## FAQ [#faq] One seat is one machine at a time. Deactivate on the desktop, activate on the laptop — it takes about a minute in the dashboard. If you switch machines daily, a second seat is the honest answer. The operator keeps working at the last version released during your term. Renewing restores update access — nothing on your machine deactivates. Yes — activation has an offline path built for media servers that never touch the internet. See [Activation → Offline](/docs/getting-started/activation#offline-activation). Planned, not live. [Contact us](/contact) with your institution and we'll sort something out manually in the meantime. # Requirements (/docs/getting-started/requirements) NativeOps plugins are native CUDA code sharing TouchDesigner's GPU. The requirements below are hard floors, not recommendations — the operators check them at load time and say so in the status parameter when one is missing. ## Supported platforms [#supported-platforms] | | Minimum | Recommended | | ------------- | --------------- | -------------------- | | TouchDesigner | 2023.12000 | 2025.30000+ | | Windows | Windows 10 21H2 | Windows 11 | | NVIDIA driver | 560.xx | Latest Studio driver | | CUDA compute | 7.5 (Turing) | 8.9+ (Ada) | | VRAM | 6 GB | 12 GB+ | macOS is not supported. Every NativeOps plugin depends on CUDA — and Photon additionally on the RTX SDKs — which do not exist on Apple silicon. This is an NVIDIA-only product line by design. ## GPU generations [#gpu-generations] The RTX requirement differs by plugin: | Plugin | Needs RT cores | Runs on GTX | | ------------ | ---------------------------- | ---------------- | | Photon RTXPT | Yes — RTX 20-series or newer | No | | Photon OVRTX | Yes — RTX 20-series or newer | No | | Matter | No — any CUDA 7.5+ GPU | Yes (16-series+) | | Aura | No — any CUDA 7.5+ GPU | Yes (16-series+) | Multi-GPU rigs: the operator cooks on whichever adapter TouchDesigner is running on. Affinity across GPUs is on the [roadmap](/roadmap), not in the current builds. ## Checking your machine [#checking-your-machine] ```python title="Textport" # TouchDesigner build print(app.build) # GPU + driver as TouchDesigner sees them print(project.paths) # placeholder — see the Guides section ``` If the machine falls short, [Troubleshooting → GPU requirements](/docs/troubleshooting/gpu-requirements) has the full decision tree. # Your first path-traced frame (/docs/guides/first-render) This guide assumes an [installed](/docs/getting-started/installation) and [activated](/docs/getting-started/activation) Photon RTXPT. Watermark mode works too — everything renders, watermarked. ### Make some geometry [#make-some-geometry] A Grid SOP as the floor and a Torus SOP floating above it. Nothing fancy — this scene is about light, not modeling. ### Drop the renderer [#drop-the-renderer] Add a `Photon RTXPT` TOP from the OP Create dialog's **Custom** tab. Point its `Geometry` parameter at the container holding both SOPs: ```python title="Or from the Textport" op('photon_rtxpt1').par.geometry = '/project1/geo1' ``` You already have an image — the default camera orbits the scene bounds and a default dome light fills it. ### Light it on purpose [#light-it-on-purpose] Add a `Photon Light` COMP, type **Area**, and set intensity to `10000` lumens. Kill the default dome by setting the renderer's `Default Dome` toggle off. One soft key from the left — already worth a screenshot. ### Give the floor a material [#give-the-floor-a-material] Add a `Photon Material` COMP, set `Roughness` to `0.15`, and bind it: ```python op('photon_mat1').par.bindpaths = '*/grid*' ``` The torus keeps the default gray; the floor picks up a soft reflection of it. ### Let it converge [#let-it-converge] Stop moving the camera and watch the sample counter climb in the info overlay — the image resolves in a second or two. That's accumulation; it resets on any move and the denoiser hides the restart. ## Where to go from here [#where-to-go-from-here] Glass and emission are two parameters away. Swap the area for a sun + dome pairing. Drop a Movie File Out TOP after the renderer and you have path-traced playblasts — accumulation makes still-camera exports look like offline renders. # Guides (/docs/guides) Reference pages say what a parameter does; guides say what to do. Each one is a complete path through a real task, with the wrong turns marked. Empty network to a denoised Photon RTXPT render in ten minutes. Seats on headless nodes — offline activation at rack scale. More guides land with the plugins — coupling recipes for Matter, an Aura scene-lighting cookbook, and a DMX-to-Photon rig walkthrough are next in the queue. [Tell us](/contact) what you're stuck on. # Licensing a render farm (/docs/guides/render-farm-licensing) Render nodes are the worst-case licensing client: no browser, often no internet, imaged from a common template. This guide runs the [offline activation](/docs/getting-started/activation#offline-activation) flow at rack scale. Do **not** bake an activated seat into a machine image. The license fingerprint covers GPU and motherboard — clones fail validation on first cook and show up in your dashboard as conflicting activations. ## The flow [#the-flow] ### Generate requests on every node [#generate-requests-on-every-node] Photon and Matter ship a headless license tool next to the DLL — scriptable over your farm's remote execution: ```powershell title="Per node, via your farm manager" & "C:\Program Files\Derivative\TouchDesigner\Plugins\PhotonRTXPT\nops-license.exe" ` request --out \\filer\licenses\requests\$env:COMPUTERNAME.request ``` ### Bulk-upload in the dashboard [#bulk-upload-in-the-dashboard] [Dashboard → Seats → Offline activation](/dashboard) accepts a zip of request files and returns a zip of `seat.license` files, one per node, named by machine. ### Distribute the license files [#distribute-the-license-files] ```powershell title="Back out over the same channel" Copy-Item "\\filer\licenses\issued\$env:COMPUTERNAME.license" ` -Destination "C:\Program Files\Derivative\TouchDesigner\Plugins\PhotonRTXPT\seat.license" ``` Nodes pick the file up on the next TouchDesigner launch — no reboot. ### Verify from the farm manager [#verify-from-the-farm-manager] The tool exits nonzero on an unlicensed node, so your farm's health check can gate dispatch: ```powershell & "...\nops-license.exe" status --quiet # 0 = licensed ``` ## Swapping hardware [#swapping-hardware] GPU replacement invalidates that node's fingerprint. Deactivate the seat in the dashboard *before* the swap and reissue afterwards — takes two minutes and avoids the conflicting-activation flag. Farm seats are ordinary seats — same price, same dashboard. If a node dies mid-season, dashboard-deactivate it and the seat is immediately free for the replacement. # Coupling (/docs/matter/coupling) **Coupling** is the suite's reason to exist: all body types integrate on the same clock, so forces exchange *inside* a substep instead of one frame late. A splash pushes the boat during the same step the boat displaces the water. ## What couples with what [#what-couples-with-what] | | Rigid | Fluid | Cloth | | --------- | ------------------ | ---------------------- | ------------------------- | | **Rigid** | contacts, stacking | buoyancy, drag, splash | drape, collide | | **Fluid** | displacement | — | soak weight, surface drag | | **Cloth** | wraps, tears | porous flow-through | self-collision | ## Enabling it [#enabling-it] Coupling is on by default between bodies in the same solver. The switch that matters is the pair mask: ```python title="Turn off fluid→cloth for a cheap win" solver = op('matter_solver1') solver.par.couplefluidcloth = False # banner ignores the rain ``` Pair masks are the first performance lever. A courtyard scene where rain never believably moves the flags can drop fluid→cloth and win the substep back. ## Walkthrough: boat on water [#walkthrough-boat-on-water] Drop a `Matter Solver`, a `Matter Fluid` fed by a tank-shaped SOP, and a `Matter Rigid` pointed at the boat mesh with `Collision Shape: auto-convex`. Set boat `Density` below the fluid's rest density — 400 kg/m³ floats convincingly against water's 1000. Read the boat transform out of `Matter Out` into a Geometry COMP instance. The camera never knows the hull is a proxy. Coupled systems share the substep budget — a fluid at 2 substeps forces the rigids it touches down to 2 as well. If stacking gets soft the moment fluid enters the scene, raise the solver's substeps, not the rigid's stiffness. # Overview (/docs/matter) **Matter** is a simulation suite, not a collection of solvers. Rigid bodies, fluids, cloth, and constraints all step on one clock inside one CUDA context — which is what lets a fluid push a box that tears a cloth, in real time, without a frame of latency between them. Matter runs on any CUDA 7.5+ GPU — RT cores not required. A GTX 16-series laptop runs the small examples; see [Requirements](/docs/getting-started/requirements). ## The suite [#the-suite] One solver, three body types, two force fields, an emitter, and a readback CHOP — the whole surface. Solvers exchange impulses inside a substep, not across frames — the feature the suite is built around. ## Design rules [#design-rules] * **Determinism switch.** `Deterministic` on the solver trades \~15% speed for bit-identical replays — same inputs, same frames, every run. * **SOPs in, SOPs/TOPs out.** Colliders and emitters are plain geometry; results come back as point clouds, meshes, or velocity fields. * **Budgeted stepping.** Like Photon OVRTX, the solver takes a millisecond budget and reduces substeps before it ever stalls your frame. ## FAQ [#faq] No — Matter's solvers are written for the GPU-resident, two-way-coupled case. A wrapper around a CPU engine can't share substep impulses with a GPU fluid without copying state across the bus every step. Placeholder targets on a 4080: \~20k active rigid bodies, \~2M fluid particles, or \~500k cloth vertices — budget-shared when mixed. Real numbers land with the benchmark project. The readback CHOP/SOP pair feeds TouchDesigner's native caching (Cache SOP, File Out). A dedicated bake operator is on the [roadmap](/roadmap). # Operators (/docs/matter/operators) Eight operators, one pattern: the **solver** owns time, everything else declares state or reads it back. | Operator | Family | Role | | ------------------- | ------ | ------------------------------------------- | | `Matter Solver` | COMP | The clock — owns substeps, gravity, budget | | `Matter Rigid` | COMP | Rigid body set from SOP instances | | `Matter Fluid` | COMP | SPH fluid volume | | `Matter Cloth` | COMP | Cloth / soft shell from a mesh | | `Matter Constraint` | COMP | Joints, motors, pins between bodies | | `Matter Force` | COMP | Field forces — wind, vortex, attractors | | `Matter Emitter` | COMP | Streams new particles / bodies at rate | | `Matter Out` | CHOP | Readback — transforms, velocities, contacts | ## Network shape [#network-shape] ```text title="Typical wiring" matter_solver1 ├─ matter_rigid_crates (SOP: crate instances) ├─ matter_fluid_tank (SOP: emission volume) ├─ matter_cloth_banner (SOP: banner mesh) ├─ matter_force_wind └─ matter_out1 (CHOP → instancing network) ``` Bodies register with the solver whose path their `Solver` parameter names — parenting in the network editor is for humans, the path is what binds. One solver per interacting system. Two solvers never exchange forces — use that deliberately to isolate a background sim from a hero sim at different budgets. ## Reading results [#reading-results] ```python title="Contacts drive audio" contacts = op('matter_out1')['contact_impulse'] if contacts.eval() > 4.0: op('audio_hit').par.play.pulse() ``` `Matter Out` exposes contacts as CHOP events with impulse magnitude — collision-driven sound and lighting cost one export, no Python per frame. # Parameter reference (/docs/matter/parameters) Generated reference (same pipeline as Photon's) — Matter is the reason it exists: eight operators, \~160 parameters, derived from USD Physics schemas. Placeholder subset below. ## Matter Solver — Sim page [#matter-solver--sim-page] ## Matter Rigid — Body page [#matter-rigid--body-page] ## Full table [#full-table] | Operator | Page | Parameters | | ---------- | -------- | ----------------------------------------------- | | Solver | Sim | substeps, budget, gravity, deterministic, scale | | Solver | Advanced | broadphase, sleep threshold, CFL target | | Rigid | Body | density, friction, restitution, shape | | Fluid | Volume | rest density, viscosity, surface tension | | Cloth | Shell | stretch, bend, thickness, self-collide | | Constraint | Joint | type, limits, motor target, stiffness | | Force | Field | type, strength, falloff, noise | | Emitter | Rate | rate, speed, lifetime, inherit velocity | | Out | Channels | transforms, velocities, contacts, ids | # Overview (/docs/photon-ovrtx) **Photon OVRTX** is the second Photon renderer. Same operators, same materials, same lights — a different engine underneath. Where [RTXPT](/docs/photon-rtxpt) converges to a reference-grade frame, OVRTX holds a stable interactive image under constant scene churn. Scenes are **portable between the two Photons**. The operator surface is shared, so switching engines is replacing one TOP — bindings, lights, and cameras carry over untouched. ## When to reach for OVRTX [#when-to-reach-for-ovrtx] | You are doing | Use | | --------------------------------------------- | --------------------------- | | Previz with a director dragging lights around | **OVRTX** | | Look development toward a final still | [RTXPT](/docs/photon-rtxpt) | | Live show output at frame rate | **OVRTX** | | Fixture-accurate lighting sign-off | [RTXPT](/docs/photon-rtxpt) | ## What differs from RTXPT [#what-differs-from-rtxpt] * **Radiance caching** — indirect light amortizes across frames; a moving camera doesn't restart the world * **Fixed frame budget** — set milliseconds, not samples; quality scales to fit the frame time you have left * **No accumulation state** — every frame is complete, so downstream feedback loops behave The trade: OVRTX's indirect lighting is approximate. Caustics, deep glass, and long light chains resolve on RTXPT only. ## Next steps [#next-steps] Shared surface, engine-specific pages flagged. The OVRTX-only parameters, next to the shared set. # Lights (/docs/photon-ovrtx/lights) Light types and units are shared with [RTXPT → Lights](/docs/photon-rtxpt/lights) — lumens, lux, nits, EV. What changes on OVRTX is *how many* lights stay cheap. ## Light counts [#light-counts] RTXPT samples lights stochastically — hundreds are fine. OVRTX shades a bounded set per pixel: | Tier | Count | Cost | | ------------------- | --------- | ----------------------------------- | | Shadowed key lights | up to 8 | full shadows every frame | | Cached contributors | up to 256 | shadows via radiance cache | | Beyond that | unlimited | ambient pool, no individual shadows | The engine promotes and demotes lights automatically by contribution; pin one with its **Priority** parameter when a cue depends on it. Concert rigs: leave moving heads in the cached tier and pin only followspots. Promotion churn during a blackout snap is what the Priority pin exists for. A DMX-driven light strobing at cache frequency defeats the cache — flag fast-flicker fixtures with `Animate → Realtime` so they bypass it and shade directly. # Materials (/docs/photon-ovrtx/materials) Materials are **defined once, rendered twice** — the same `Photon Material` COMP feeds both engines. This page covers what OVRTX does differently with them; the models themselves are documented under [RTXPT → Materials](/docs/photon-rtxpt/materials). ## Fidelity by model [#fidelity-by-model] | Model | On OVRTX | Notes | | ---------- | ----------- | --------------------------------------------- | | Principled | Full | Indistinguishable from RTXPT in most lighting | | Emission | Full | Feeds the radiance cache directly | | Glass | Approximate | Single refraction event; no nested interfaces | Glass-heavy hero shots are the one place scene portability has an asterisk: OVRTX renders one refraction bounce and estimates the rest. Preview on OVRTX, sign off on RTXPT. ## Texture streaming [#texture-streaming] OVRTX streams bound TOP textures at half resolution while their content changes, snapping to full when stable for a few frames — this keeps Movie File In TOPs from stalling the frame budget. ```python title="Force full-res for a critical surface" op('photon_mat_screen').par.streamquality = 'full' # opt out per material ``` The half-res window is invisible on diffuse channels and noticeable on normal maps — flag hero normal-mapped materials `full` and leave the rest on `auto`. # Operators (/docs/photon-ovrtx/operators) OVRTX reuses the Photon helper COMPs — only the renderer TOP is its own operator. If both plugins are installed, the helpers serve whichever renderer collects them. | Operator | Family | Shared with RTXPT | | ----------------- | ------ | ----------------- | | `Photon OVRTX` | TOP | — (the engine) | | `Photon Material` | COMP | Yes | | `Photon Light` | COMP | Yes | | `Photon Camera` | COMP | Yes | ## The frame budget [#the-frame-budget] The defining OVRTX control is on the Render page: ```python title="Textport" render = op('/project1/photon_ovrtx1') render.par.framebudget = 8.0 # ms — leave headroom for the rest of the network ``` The engine spends its budget in priority order — primary visibility first, then shadows, then the radiance cache. Starve it and the image degrades gracefully instead of dropping frames. Running at 60 fps with a 16.6 ms frame? Give OVRTX 8–10 ms and keep the rest for compositing. The `Perform` page's cook-time readout tells you what the whole chain actually costs. A `Photon Material` bound in an RTXPT project needs no edits here — engine differences are absorbed by the renderer, not pushed into your scene. # Parameter reference (/docs/photon-ovrtx/parameters) Generated reference — same pipeline as [RTXPT's](/docs/photon-rtxpt/parameters). Placeholder subset until the generator lands. Shared pages (Scene, Output, Activate) are identical across both Photons and documented once there. ## Render page (OVRTX) [#render-page-ovrtx] ## Reading the health readouts [#reading-the-health-readouts] The Info page reports where the budget went: | Readout | Healthy | Investigate when | | ---------------- | -------- | ---------------------------------------------- | | `budget_used_ms` | ≤ budget | pegged at budget every frame | | `cache_hit_rate` | > 0.8 | \< 0.5 — density too low for the scene scale | | `stale_probes` | \~0 | climbing — geometry churning faster than refit | `Cache Density` below 0.1 in a stadium-scale scene allocates probe grids in the gigabytes. Scale density with scene scale — the default 0.5 assumes meters. # Overview (/docs/photon-rtxpt) **Photon RTXPT** is a path tracer that lives in your network. Geometry comes in as SOPs or USD, lights and cameras are COMPs you already know, and the render lands in a TOP — denoised, tone-mapped, and ready for compositing. Photon RTXPT requires an RTX GPU (20-series or newer) — the path tracer runs on RT cores. See [Requirements](/docs/getting-started/requirements). ## How it renders [#how-it-renders] A **frame is a cook**. Every time the operator cooks it traces a configurable number of paths per pixel, accumulates against the previous frames when the scene is static, and runs the DLSS Ray Reconstruction denoiser before output. Move the camera and accumulation resets automatically. SOP and USD inputs become RTX acceleration structures incrementally — only what changed re-uploads, so animated geometry stays interactive. Materials, lights, and camera exposure follow the same physical units as offline renderers — lumens, EV, and metric scene scale. ## What's in the box [#whats-in-the-box] * One render TOP with the full parameter surface — [operators](/docs/photon-rtxpt/operators) has the map * Principled, emission, and glass [materials](/docs/photon-rtxpt/materials) * Area, sun, dome, and mesh [lights](/docs/photon-rtxpt/lights) * A [parameter reference](/docs/photon-rtxpt/parameters) generated from the same source that registers them in TouchDesigner ## Next steps [#next-steps] The operator set and how they wire together. Every page, every parameter, with ranges and defaults. From empty network to a denoised path-traced frame. Confirm your hardware before you buy. # Lights (/docs/photon-rtxpt/lights) Every **Photon Light** works in physical units — lumens for emitters, lux for the sun, EV-relative intensity everywhere. Match a lighting plot's numbers and the render agrees with the venue. ## Light types [#light-types] | Type | Shape | Intensity unit | Shadows | | ---- | -------------------- | -------------- | ----------------------- | | Area | rect / disc / sphere | lumens | soft, size-driven | | Sun | directional | lux | sharp, angular-diameter | | Dome | HDRI environment | EV offset | image-based | | Mesh | any SOP | nits | from geometry | ## Driving lights live [#driving-lights-live] Light parameters accept CHOP exports without resetting accumulation — they're part of the light-sampling pass, not the scene build. ```python title="DMX → Photon" # sACN in a CHOP, mapped straight onto a light op('photonlight_key').par.intensity.expr = "op('sacn1')['u1c1'] * 15000" ``` Dome + area is the standard stage recipe: dome at −2 EV for ambience, area lights carrying the key. Start there before adding mesh emitters — they are the most expensive type to sample. A mesh light with thousands of triangles samples poorly and shows as noise in shadows. Decimate emitter geometry to the silhouette — the light looks identical and converges far faster. # Materials (/docs/photon-rtxpt/materials) A **Photon Material** binds a look to geometry by path pattern. Any channel can be a constant or a TOP — textures stay on the GPU end to end. ## Material models [#material-models] The workhorse — a Disney-style BSDF matching what your offline renderer calls Standard Surface. | Channel | Takes | Default | | ---------- | ----------- | -------- | | Base Color | RGB / TOP | 0.8 gray | | Roughness | float / TOP | 0.5 | | Metallic | float / TOP | 0 | | Normal | TOP | — | Anything can glow. Emission is in **nits** so LED-wall content reads at believable levels next to physical lights. | Channel | Takes | Default | | ----------------- | ------------ | ------- | | Emission Color | RGB / TOP | white | | Intensity (nits) | float / CHOP | 100 | | Visible to Camera | toggle | on | Real refraction, not a transparency hack. Budget bounces accordingly — see the Note below. | Channel | Takes | Default | | ---------------- | ----------- | ------- | | IOR | float | 1.45 | | Roughness | float / TOP | 0 | | Absorption Color | RGB | white | Glass needs path depth: at the default 4 bounces a glass-in-front-of-glass shot goes black where paths run out. Raise `Max Bounces` to 6–8 for transmissive scenes and watch the ms/frame readout. ## Binding [#binding] ```python title="Photon Material COMP — Binding page" # Bind by path pattern, most-specific pattern wins op('photon_mat_floor').par.bindpaths = '*/floor_geo' op('photon_mat_hero').par.bindpaths = '*/hero/*' ``` Unbound geometry gets the default gray Principled — a scene never fails to render because a pattern missed. Wildcards make LOD swaps free: bind `*/statue_*` once and every resolution variant inherits the same look. # Operators (/docs/photon-rtxpt/operators) Photon RTXPT installs one renderer and three helper operators. The renderer owns the GPU pipeline; the helpers describe the scene. | Operator | Family | Role | | ----------------- | ------ | ----------------------------------------------- | | `Photon RTXPT` | TOP | The renderer — traces, denoises, outputs | | `Photon Material` | COMP | A material definition bound by path or wildcard | | `Photon Light` | COMP | A light — area, sun, dome, or mesh emitter | | `Photon Camera` | COMP | Physical camera: focal length, aperture, EV | ## Assembling a scene [#assembling-a-scene] ```python title="Textport — minimal scene" render = op('/project1/photon_rtxpt1') render.par.geometry = '/project1/geo1' # any SOP hierarchy render.par.camera = '/project1/photoncam1' # falls back to a default cam render.par.lights = '/project1/photonlight*' # wildcard collect ``` The renderer collects by **path pattern** — the same wildcard rules as any TouchDesigner parameter that takes an OP path. Drop a new `Photon Light` matching the pattern and it joins the next cook. Helper COMPs cook at parameter-change time only. The renderer is the only operator doing per-frame work — keep your cull flags on the SOPs feeding it, not on the Photon COMPs. ## Cook behavior [#cook-behavior] * **Static scene** → progressive accumulation, up to the `Max Samples` cap * **Camera move** → accumulation resets, denoiser bridges the gap * **Geometry edit** → only the touched acceleration structure rebuilds Time-sliced CHOP exports into material parameters force a full reset every frame. Route animated values through the `Photon Material` COMP's dedicated Animate page instead — those update without invalidating accumulation. # Parameter reference (/docs/photon-rtxpt/parameters) This reference is **generated** — the same source that registers parameters with TouchDesigner emits these tables, so they cannot drift from the build. Placeholder subset below until the generator lands. ## Render page [#render-page] ## Output page [#output-page] ## Full table [#full-table] | Page | Parameter | Type | Default | | -------- | -------------- | ---------- | ----------- | | Render | Samples / Cook | int | 1 | | Render | Max Samples | int | 1024 | | Render | Max Bounces | int | 4 | | Render | Denoiser | menu | DLSS-RR | | Render | Exposure | float | 0 | | Output | Resolution | wh | 1920 × 1080 | | Output | Tone Map | menu | ACES | | Output | AOV Layers | toggles | off | | Scene | Geometry | OP path | — | | Scene | Camera | OP path | — | | Scene | Lights | OP pattern | — | | Scene | Scene Scale | float | 1.0 | | Advanced | Ray Offset | float | 0.0001 | | Advanced | Firefly Clamp | float | 8.0 | | Activate | License Key | string | — | # Activation problems (/docs/troubleshooting/activation-problems) Activation failures are deliberately specific — the `Status` readout names the exact refusal. Find yours below. Three causes, in frequency order: a typo (keys are `NOP-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` — 36 characters after the prefix, so the dashboard's copy button beats retyping), a key for a *different plugin* (keys are plugin-scoped), or a revoked key after a refund. The [dashboard](/dashboard) shows each key's plugin and state. The seat is active elsewhere — possibly a dead machine that never got the chance to deactivate. Free it from the [dashboard](/dashboard) (**Seats → Deactivate**); the change is immediate, no support ticket needed. The `seat.license` was issued for different hardware. Regenerate the `machine.request` *on the machine as it is now* and reissue — this hits people who swapped a GPU, and farm operators who cloned an image with a request file baked in. Offline licenses carry a signed timestamp. Air-gapped machines drift; more than 48 hours breaks validation. Set the clock (GPS/NTP appliance on show networks), regenerate, reissue. The machine can't reach the licensing endpoint. Corporate TLS inspection is the usual culprit — ask IT to exempt `licensing.nativeops.tools`, or use [offline activation](/docs/getting-started/activation#offline-activation), which exists for exactly this network. None of it matching? [Contact support](/contact) with the Info DAT diagnostics dump (right-click the operator → **Copy Diagnostics**) — it includes the last ten status transitions, which is usually the answer. # Drivers (/docs/troubleshooting/drivers) Driver bugs present as **device-lost crashes** mid-session or as denoiser artifacts — not as load failures. If the operator loads and then the GPU resets under load, start here. Short version: run the latest **Studio** driver. Game Ready drivers ship first and regress compute paths more often; Studio is the same driver on a slower, better-tested cadence. ## Known ranges (placeholder) [#known-ranges-placeholder] | Driver range | Symptom | Verdict | | --------------- | ------------------------------- | ---------------- | | 572.00 – 572.42 | DLSS-RR denoiser NaN flashes | Skip | | 566.xx | Stable everywhere we test | Floor for Photon | | \< 560.00 | Load refused (`Driver too old`) | Hard floor | ## The clean-install ritual [#the-clean-install-ritual] When a machine misbehaves on a driver that's fine elsewhere: Download the current Studio driver directly from NVIDIA — not Windows Update, not GeForce Experience. Run the installer with **Custom → Perform a clean installation** checked. This clears cached shader blobs and stale settings profiles, which is the actual fix more often than the driver version. Reboot, then delete TouchDesigner's own shader cache folder so nothing stale is replayed against the new driver. Enterprise/vPro fleets that pin drivers via SCCM: the pinned driver is usually months behind the floor. The plugins print the minimum version in the status string — hand that line to IT, it is the whole conversation. # GPU requirements (/docs/troubleshooting/gpu-requirements) At load, every operator runs the same checks in order and stops at the first failure — the `Status` readout names it. Work down the same list. ### `No CUDA device` [#no-cuda-device] TouchDesigner isn't running on the NVIDIA GPU. On laptops, force it: NVIDIA Control Panel → Manage 3D Settings → Program Settings → TouchDesigner → **High-performance NVIDIA processor**. ### `CUDA version` — compute capability below 7.5 [#cuda-version--compute-capability-below-75] The GPU predates Turing (GTX 10-series or older). No setting fixes this — see the support matrix in [Requirements](/docs/getting-started/requirements). ### `GPU unsupported` — RT cores missing (Photon only) [#gpu-unsupported--rt-cores-missing-photon-only] GTX 16-series has CUDA 7.5 but no RT cores: Matter and Aura run, the Photons refuse. This is the one row where plugins diverge. ### `Out of memory` at first cook [#out-of-memory-at-first-cook] The checks passed; the scene doesn't fit. Drop the internal resolution preset, or close Chrome — its GPU process routinely holds 1–2 GB. ## FAQ [#faq] Almost always Optimus: the laptop is cooking TouchDesigner on the iGPU. The `No CUDA device` step above fixes it. Verify with the Info DAT — `gpu_name` should say NVIDIA, not Intel/AMD. Not yet — the operator cooks on TouchDesigner's active adapter. Multi-GPU affinity is on the [roadmap](/roadmap). Shared system memory counts toward nothing: the 6 GB floor means dedicated VRAM. A 4 GB dedicated + 8 GB shared laptop fails the check honestly. # Troubleshooting (/docs/troubleshooting) Every NativeOps operator reports its state in the `Status` readout on the Common page. That string is the fastest route to the right page below. | Status says | Go to | | --------------------------------------- | ---------------------------------------------------------------- | | `GPU unsupported` / `CUDA version` | [GPU requirements](/docs/troubleshooting/gpu-requirements) | | `Driver too old` / device-lost crashes | [Drivers](/docs/troubleshooting/drivers) | | `License invalid` / `Activation failed` | [Activation problems](/docs/troubleshooting/activation-problems) | | Operator missing from OP Create | [Installation](/docs/getting-started/installation) | The load-time hardware checks and what each failure means. Known-bad driver ranges and the clean-install ritual that fixes most device-lost errors. Key rejected, seat conflicts, offline files that won't take. Filing a [support request](/contact)? Attach the operator's Info DAT dump (right-click → **Copy Diagnostics**) — it carries the plugin build, driver, GPU, and the last ten status transitions, and it turns most tickets into one-reply fixes.