PT / GI Packs

pt_surface.hlsl: shade a pack in the path tracer and the offline GI renderer. PackEvaluate, PtPackIn / PtPackOut, textures, the denoiser and limits.

What a PT / GI pack is

A surface pack (surface.hlsl) shades the raster and ray-traced camera views with PackShade. The path tracer (--render pt, the PT video renderer) and the offline GI renderer (GI stills and videos) trace every ray inside one compute shader, so PackShade cannot run there. A pack can opt in with a second file, pt_surface.hlsl, that describes the material at a hit. The renderer keeps the light transport: sun shadows, indirect light, the irradiance cache and the denoiser.

This needs MMDX12 1.5.0 or newer. A pack without the file uses the default shading in PT and GI, and older versions ignore the file.

Files

my_pack/
  pack.json        manifest (unchanged)
  surface.hlsl     raster / real-time RT    (PackShade)
  pt_surface.hlsl  path tracer / offline GI (PackEvaluate)
  shared.hlsli     optional: maths both files include

Both files can #include "shared.hlsli" from the pack folder, so the look is written once. The online gallery pack nimble_toon does exactly this.

PackEvaluate

PtPackOut PackEvaluate(PtPackIn i);

PtPackIn

FieldMeaning
pos, normal, V, uvworld position, shading normal, direction to the camera, texture coordinates
L, sunVisdirection to the sun, sun visibility 0..1 from the traced shadow ray (0 on diffuse bounces)
baseColorlinear texture colour times the material colour, no lighting
materialClassPACK_BODY / SKIN / FACE / EYE / HAIR / WEAPON from your classes rules
params[16]your sliders, in pack.json order
headPos, headScale, headRight, headUp, headForward, headValidthe head bone frame, as in PackSurface

PtPackOut (assign every field; pack_check warns when one is never assigned)

FieldMeaning
albedolinear surface colour; what diffuse bounces and the denoiser see
shadowTintlinear multiplier for the shaded side
shadowBiasshifts the terminator in N.L units (a smoothed face normal: dot(Nsmooth, L) - dot(normal, L))
terminator(lo, hi) N.L edges of the terminator smoothstep; (0, 0) = the engine default
specularadditive linear radiance (rim, gloss, matcap); multiplied by sunVis
flatFaceuse the engine’s flat-face handling (no indirect gradient on this surface)

How the renderer uses it

  • Camera rays and mirror / glass chains: lerp(albedo * shadowTint, albedo, term * sunVis) * sunIntensity + specular * sunVis, where term = smoothstep(lo, hi, N.L + shadowBias).
  • Diffuse bounces (light gathered by other surfaces): only albedo is used. Toon terms never run on gather rays.
  • Do not add an ambient term: the path tracers trace the real indirect light.
  • A half-Lambert ramp threshold +- softness maps to terminator = (2 * (threshold - softness) - 1, 2 * (threshold + softness) - 1).

Textures

The textures declared in pack.json are available (explicit LOD only, no implicit derivatives):

float4 PtPackSampleTex(uint i, float2 uv);                 // level 0
float4 PtPackSampleTexLevel(uint i, float2 uv, float lod);
uint   PtPackTexCount();
float2 PtPackTexSize(uint i);

An out-of-range index or a missing file gives white, as in PackSampleTex. sRGB textures sample as linear values.

Limits

  • Characters only; stages and props are never shaded by packs.
  • With several different PT packs in one scene the first is used (a warning is logged).
  • The offline GI renderer draws the app’s default outlines (PackEdge applies to raster and RT).
  • The denoiser treats the pack’s direct light like the default toon light. A hard step() highlight kept crisp edges in a still test; fast motion was not checked.
  • Avoid unbounded loops in PackEvaluate: a GPU hang closes the app.
  • Check a pack with pack_check <dir> --compile: it compiles the raster, offline GI and path tracer variants.