code wiki / (root) / nx_gi_path_lib.nx

nx_gi_path_lib.nx

buildroot/runtime/nx_gi_path_lib.nx

16498 B316 linesdepth 4pulls 7 transitivereach 2 importersview sourcekind librarytopic gi
docsdependenciesstructsconstsfunctions

about

nx_gi_path_lib.nx -- THE BEAUTY TIER'S FIRST BYTE (LIBRARY: every function of the sovereign path tracer; nx_gi_path.nx is the CLI, nx_gi_path_gate.nx the teeth): a sovereign INTEGER PATH TRACER over the procgen heightfield. graphics GR42 (env_beauty_scene) + GR10 (gp_bounce_gi); operator 2026-09-02, looking at /world/beach: "that looks like our junk cpu stuff ... lets get things infinigen generating to photoreal". Infinigen renders offline through a path tracer; this organ is that twin, first byte up: no float, no library, no third party -- the same fx1024 arithmetic, the same fBm heightfield (nx_worldgen wg_terrain_h), the same sky model (wg_sky), the same soft-shadow march (wg_sun_pen) and the same PNG writer the estate already ships. What is NEW is the light transport: every pixel is the mean of spp Monte Carlo paths, each path = primary ray -> Lambertian hit (direct sun x soft shadow) -> cosine- weighted bounce (BRDF x cos / pdf = albedo, so no division noise) -> up to GP_BOUNCES hits -> sky gather when the path escapes. Colour bleed and sky occlusion therefore emerge from transport instead of being painted on, which is the difference between the raymarcher's "ambient = 42" and a beauty tier. DETERMINISM: the sampler is a seeded integer LCG advanced per draw; two runs with the same argv are byte-identical, so a gate can diff frames (the GR10 cache-vs-rebuild law carried into path tracing). NO TERRACING: the march step grows with distance (footprint-sized) and every hit is REFINED by GP_REFINE bisections, so the surface lands within a fraction of a unit -- the stair-steps visible in every nx_worldgen slope are gone. HONEST LIMITS OF THIS FIRST BYTE, stated so the next reader does not credit them: terrain is Lambertian only (no specular, no BRDF model beyond albedo); water is a single mirror event tinted by a deep colour, not refraction; the sky is nx_worldgen's gradient+sun+cloud model, not GR26's Rayleigh/Mie atmosphere; no cast meshes yet; no depth/normal/semantic ground-truth siblings yet (the dataset half of GR42). Each of those is a named rung. UNITS: directions are fx1024 unit vectors; radiance is carried as throughput(fx1024) x colour(0..255), then averaged, Reinhard-mapped and display-encoded ONCE at output (GR14's linear-light law: all transport in linear). nx_gi_path <out.png> [seed] [spp] [weather 0 clear | 1 sunset | 2 overcast] [yaw 0..4095] exit: 0 written | 2 usage | 5 png-write-fail. license_tier: ORIGINAL No hw writes (Rule 26).

dependencies 5 imports · 2 importers

nx_syscalls.nx nx_itrig.nx nx_vecmath.nx nx_worldgen.nx nx_png_write.nx nx_gi_path_lib.nx nx_gi_path.nx nx_gi_path_gate.nx

imports: nx_syscalls.nxnx_itrig.nxnx_vecmath.nxnx_worldgen.nxnx_png_write.nx

imported by: nx_gi_path.nxnx_gi_path_gate.nx

structs

none

consts

33const GP_FRAC_NUM: i64 = 3
34const GP_FRAC_DEN: i64 = 8
35const GP_FX: i64 = 1024 // the estate's fixed-point unit, the one nx_worldgen's vectors already use
36const GP_HALF: i64 = 512 // half a fx unit: the pixel-jitter recentring term
37const GP_CIRCLE: i64 = 4096 // it_sin4096: 4096 angle units per turn AND amplitude 4096
38const GP_SPP_DEFAULT: i64 = 4
39const GP_BOUNCES: i64 = 2 // primary + 2 diffuse bounces: the shortest transport that carries colour bleed AND sky occlusion
40const GP_T0: i64 = 4 // first march distance in front of an origin
41const GP_BIAS: i64 = 8 // bounce origin lifted along the normal so a path never re-hits its own surface
42const GP_TMAX: i64 = 60000 // nx_worldgen's far plane
43const GP_SKY_Y: i64 = 2900 // nx_worldgen's sun-march ceiling: no terrain exists above it
44const GP_STEP_MIN: i64 = 6
45const GP_STEP_DIV: i64 = 96 // step = min + t/96: half the raymarcher's growth (t/48), then bisection-refined
46const GP_REFINE: i64 = 8 // bisections per hit: the last step / 256 -> sub-unit placement, no terracing
47const GP_MAX_STEPS: i64 = 400
48const GP_NRM_EPS: i64 = 24 // the raymarcher's normal footprint, kept so both tiers agree on the same surface
49const GP_SUN_OVER_SKY: i64 = 2 // sun irradiance relative to the sky dome on a Lambertian surface; DECLARED, to be fitted against the reference frame
50const GP_EXPOSURE_NUM: i64 = 3 // Reinhard exposure 3/2
51const GP_EXPOSURE_DEN: i64 = 2
52const GP_MAXCH: i64 = 255 // display channel ceiling, the PNG's own
53const GP_LCG_A: i64 = 1103515245 // the classic 31-bit LCG (Numerical Recipes / glibc rand family)
54const GP_LCG_C: i64 = 12345
55const GP_LCG_MASK: i64 = 2147483647
56const GP_RND_SHIFT: i64 = 11 // drop the weak low bits of the LCG
57const GP_RND_MASK: i64 = 1023 // a draw is an fx1024 fraction
58const GP_AXIS_TILT: i64 = 600 // |n.x| above this: pick z as the helper axis when building the tangent frame
59const GP_STEEP_NY: i64 = 640 // the raymarcher's rock threshold on the normal's y
60const GP_SAND_BAND: i64 = 130 // the raymarcher's shoreline band above water
61const GP_SNOW_NY: i64 = 600 // the raymarcher's snow slope threshold
62const GP_VEG_SCALE: i64 = 1500 // the raymarcher's vegetation patch scale (world units per noise cell)
63const GP_VEG_SEED: i64 = 99
64const GP_NOISE_SPAN: i64 = 65536 // wg_vnoise range
66const GP_GRASS_R: i64 = 60
67const GP_GRASS_G: i64 = 94
68const GP_GRASS_B: i64 = 42
69const GP_GRASS_VR: i64 = 44
70const GP_GRASS_VG: i64 = 50
71const GP_GRASS_VB: i64 = 22
72const GP_ROCK_R: i64 = 112
73const GP_ROCK_G: i64 = 101
74const GP_ROCK_B: i64 = 92
75const GP_SAND_R: i64 = 198
76const GP_SAND_G: i64 = 186
77const GP_SAND_B: i64 = 152
78const GP_SNOW_R: i64 = 234
79const GP_SNOW_G: i64 = 240
80const GP_SNOW_B: i64 = 248
81const GP_WATER_R: i64 = 24
82const GP_WATER_G: i64 = 74
83const GP_WATER_B: i64 = 116
84const GP_OUT: i64 = 4096
85const GP_WORDS: i64 = 16 // scratch vectors are 16 words each (page-rounded by mmap anyway)
86const GP_EXIT_OK: i64 = 0
87const GP_EXIT_USAGE: i64 = 2
88const GP_EXIT_WRITE: i64 = 5
89const GP_CH_0: i64 = 48
90const GP_CH_9: i64 = 57
91const GP_CH_MINUS: i64 = 45
92const GP_ST_SKY: i64 = 0
93const GP_ST_WATER: i64 = 1
94const GP_ST_TERRAIN: i64 = 2
95const GP_ST_MARCHES: i64 = 3

functions

97func gp_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
98func gp_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 } return p }
called by 1: main
99func gp_num(d: *u8, o: i64, v: i64) -> i64
called by 1: main calls 2: sys_mmapsys_munmap
112func gp_atoi(s: *u8) -> i64
called by 1: main
125func gp_clamp(v: i64, lo: i64, hi: i64) -> i64 { if v < lo { return lo } if v > hi { return hi } return v }
called by 2: gp_lingp_encode
131func gp_lin(c: i64) -> i64 { let v: i64 = gp_clamp(c, 0, GP_MAXCH); return v*v*GP_FX/GP_MAXCH }
called by 2: maingp_trace calls 1: gp_clamp
133func gp_rnd(st: *i64) -> i64
called by 2: maingp_cosine_dir
138func gp_norm3(v: *i64) -> i64
146func gp_march(ox: i64, oy: i64, oz: i64, dx: i64, dy: i64, dz: i64, seed: i64, out: *i64) -> i64
called by 2: maingp_trace
190func gp_normal(hx: i64, hz: i64, seed: i64, n: *i64) -> i64
called by 1: gp_trace calls 1: gp_norm3
203func gp_albedo(hx: i64, hz: i64, hh: i64, ny: i64, seed: i64, a: *i64) -> i64
called by 2: maingp_trace
214func gp_cosine_dir(n: *i64, st: *i64, scr: *i64, d: *i64) -> i64
245func gp_trace(ox: i64, oy: i64, oz: i64, dx: i64, dy: i64, dz: i64, seed: i64, Wp: *i64, st: *i64,
309func gp_encode(m: i64) -> i64
called by 1: main calls 2: vm_isqrtgp_clamp