feat(lang): strict numbers in float files; render3d on float
A numbers float file adapts decimal literals to a fixed operand or slot, and refuses to promote a computed int to a float implicitly: there it is almost always float bits. Explicit float(x) is always allowed. render3d's numbers are float, converted by tools/migrate/floatbits.py - a whole-program inference of which ints carried IEEE bits (union-find over flows, calls, returns, buffers, nested buffers and lexical scopes) and a rewriter to operators, Math.* and float literals, with float_bits / float_from_bits left only where bits really cross (runtime scratch buffers, mixed buffers). Seed regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
3ac0d8d5cb
commit
cc89fc37a4
35 changed files with 57282 additions and 54382 deletions
|
|
@ -288,15 +288,15 @@ function tex_solid(r: int, g: int, b: int, a: int) -> int {
|
|||
}
|
||||
|
||||
# ---- Radiance .hdr (RGBE, new-style RLE) -> RGB float bits -------------------------
|
||||
var hdr_max_lum: int = 0 # float bits of the brightest texel (sun finding)
|
||||
var hdr_max_lum: float = 0.0 # float bits of the brightest texel (sun finding)
|
||||
var hdr_max_x: int = 0
|
||||
var hdr_max_y: int = 0
|
||||
var hdr_sun_r: int = 0 # irradiance (float bits) of everything above the IBL clip: the sun
|
||||
var hdr_sun_g: int = 0
|
||||
var hdr_sun_b: int = 0
|
||||
var hdr_clip: int = 0 # float bits; texels above this (per channel) feed the sun, not the IBL
|
||||
var hdr_sun_r: float = 0.0 # irradiance (float bits) of everything above the IBL clip: the sun
|
||||
var hdr_sun_g: float = 0.0
|
||||
var hdr_sun_b: float = 0.0
|
||||
var hdr_clip: float = 0.0 # float bits; texels above this (per channel) feed the sun, not the IBL
|
||||
|
||||
function hdr_decode(path: pointer) -> words {
|
||||
function hdr_decode(path: pointer) -> floats {
|
||||
let d = r3d_read_file(path)
|
||||
if d == null { print(`hdr: cannot read {path}`); return null }
|
||||
let size = tex_file_len
|
||||
|
|
@ -315,14 +315,14 @@ function hdr_decode(path: pointer) -> words {
|
|||
while d[i] >= '0' and d[i] <= '9' { w = w * 10 + (d[i] - 48); i += 1 }
|
||||
i += 1
|
||||
if w <= 0 or h <= 0 { free(d); print(`hdr: bad header {path}`); return null }
|
||||
let out = words(w * h * 3)
|
||||
let out = floats(w * h * 3)
|
||||
let line = bytes(w * 4)
|
||||
var maxl = 0
|
||||
if hdr_clip == 0 { hdr_clip = fi(20) }
|
||||
var sr = F_ZERO; var sg = F_ZERO; var sb = F_ZERO
|
||||
var skye = F_ZERO # sky irradiance on an upward face (clipped part only)
|
||||
let dphi = f_div(f_mul(F_TWO, F_PI), fi(w))
|
||||
let dth = f_div(F_PI, fi(h))
|
||||
var maxl = 0.0
|
||||
if hdr_clip == 0.0 { hdr_clip = 20.0 }
|
||||
var sr = 0.0; var sg = 0.0; var sb = 0.0
|
||||
var skye = 0.0 # sky irradiance on an upward face (clipped part only)
|
||||
let dphi = 2.0 * PI / float(w)
|
||||
let dth = PI / float(h)
|
||||
var y = 0
|
||||
while y < h {
|
||||
if d[i] == 2 and d[i + 1] == 2 and (d[i + 2] & 128) == 0 {
|
||||
|
|
@ -347,28 +347,28 @@ function hdr_decode(path: pointer) -> words {
|
|||
for x in 0 .. w { for c in 0 .. 4 { line[x * 4 + c] = d[i + x * 4 + c] } }
|
||||
i += w * 4
|
||||
}
|
||||
let sinth = f_sin(f_mul(f_add(fi(y), F_HALF), dth))
|
||||
let domega = f_mul(f_mul(dphi, dth), sinth)
|
||||
let sinth = Math.sin((float(y) + 0.5) * dth)
|
||||
let domega = dphi * dth * sinth
|
||||
for x in 0 .. w {
|
||||
let e = line[x * 4 + 3]
|
||||
let o = (y * w + x) * 3
|
||||
if e == 0 { out[o] = 0; out[o + 1] = 0; out[o + 2] = 0 }
|
||||
if e == 0 { out[o] = 0.0; out[o + 1] = 0.0; out[o + 2] = 0.0 }
|
||||
else {
|
||||
let sh = e - 136
|
||||
let vr = f_ldexp(f_from_int(line[x * 4]), sh)
|
||||
let vg = f_ldexp(f_from_int(line[x * 4 + 1]), sh)
|
||||
let vb = f_ldexp(f_from_int(line[x * 4 + 2]), sh)
|
||||
let vr = float_from_bits(f_ldexp(float_bits(float(line[x * 4])), sh))
|
||||
let vg = float_from_bits(f_ldexp(float_bits(float(line[x * 4 + 1])), sh))
|
||||
let vb = float_from_bits(f_ldexp(float_bits(float(line[x * 4 + 2])), sh))
|
||||
# the texture is capped at what a half-float holds; the sun is integrated uncapped
|
||||
out[o] = f_min(vr, fi(60000))
|
||||
out[o + 1] = f_min(vg, fi(60000))
|
||||
out[o + 2] = f_min(vb, fi(60000))
|
||||
let lum = f_add(f_add(vr, vg), vb)
|
||||
out[o] = Math.min(vr, 60000.0)
|
||||
out[o + 1] = Math.min(vg, 60000.0)
|
||||
out[o + 2] = Math.min(vb, 60000.0)
|
||||
let lum = vr + vg + vb
|
||||
if f_lt(maxl, lum) != 0 { maxl = lum; hdr_max_x = x; hdr_max_y = y }
|
||||
if y < h / 2 { skye = f_add(skye, f_mul(f_mul(f_min(vg, hdr_clip), f_cos(f_mul(f_add(fi(y), F_HALF), dth))), domega)) }
|
||||
if y < h / 2 { skye = skye + Math.min(vg, hdr_clip) * Math.cos((float(y) + 0.5) * dth) * domega }
|
||||
if f_lt(hdr_clip, vg) != 0 or f_lt(hdr_clip, vr) != 0 {
|
||||
sr = f_add(sr, f_mul(f_max(f_sub(vr, hdr_clip), F_ZERO), domega))
|
||||
sg = f_add(sg, f_mul(f_max(f_sub(vg, hdr_clip), F_ZERO), domega))
|
||||
sb = f_add(sb, f_mul(f_max(f_sub(vb, hdr_clip), F_ZERO), domega))
|
||||
sr = sr + Math.max(vr - hdr_clip, 0.0) * domega
|
||||
sg = sg + Math.max(vg - hdr_clip, 0.0) * domega
|
||||
sb = sb + Math.max(vb - hdr_clip, 0.0) * domega
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -378,7 +378,7 @@ function hdr_decode(path: pointer) -> words {
|
|||
tex_w = w; tex_h = h; tex_channels = 3; tex_depth = 32
|
||||
hdr_max_lum = maxl
|
||||
hdr_sun_r = sr; hdr_sun_g = sg; hdr_sun_b = sb
|
||||
print(`hdr: peak/1000 {f_fx(f_div(maxl, fi(1000)))} sky irradiance(up) {f_fx(skye)} sun irradiance {f_fx(sg)} (Q16.16 = /65536)`)
|
||||
print(`hdr: peak/1000 {fixed(maxl / 1000.0)} sky irradiance(up) {fixed(skye)} sun irradiance {fixed(sg)} (Q16.16 = /65536)`)
|
||||
return out
|
||||
}
|
||||
|
||||
|
|
@ -414,22 +414,22 @@ function tex_target(w: int, h: int, ifmt: int, fmt: int, ty: int, filter: int) -
|
|||
var tex_dump_alpha: bool = false
|
||||
# Debug: the brightest texel of an RGBA float texture and where it is.
|
||||
function tex_max(tex: int, w: int, h: int, tag: pointer) -> void {
|
||||
let buf = words(w * h * 4)
|
||||
let buf = floats(w * h * 4)
|
||||
gpu_tex_bind(GPU_TEX2D, tex)
|
||||
gpu_pixel_store(GL_PACK_ALIGNMENT, 4)
|
||||
gpu_tex_read(GPU_TEX2D, GL_RGBA, GL_FLOAT, buf)
|
||||
var best = F_ZERO; var bx = 0; var by = 0
|
||||
var best = 0.0; var bx = 0; var by = 0
|
||||
var i = 0
|
||||
while i < w * h {
|
||||
let v = f_max(buf[i * 4], f_max(buf[i * 4 + 1], buf[i * 4 + 2]))
|
||||
if f_gt(v, best) { best = v; bx = i % w; by = i / w }
|
||||
let v = Math.max(buf[i * 4], Math.max(buf[i * 4 + 1], buf[i * 4 + 2]))
|
||||
if v > best { best = v; bx = i % w; by = i / w }
|
||||
i += 1
|
||||
}
|
||||
print(`{tag}: max {f_fx(f_div(best, fi(100)))}/100 at {bx} {h - 1 - by} (top-down)`)
|
||||
print(`{tag}: max {fixed(best / 100.0)}/100 at {bx} {h - 1 - by} (top-down)`)
|
||||
let o = (by * w + bx) * 4
|
||||
let big = fi(65000)
|
||||
let finite = f_ls(best, big)
|
||||
print(` rgba (clamped/100): {f_fx(f_div(f_min(buf[o], big), fi(100)))} {f_fx(f_div(f_min(buf[o + 1], big), fi(100)))} {f_fx(f_div(f_min(buf[o + 2], big), fi(100)))} {f_fx(f_min(buf[o + 3], big))} finite {finite} bits {buf[o]}`)
|
||||
let big = 65000.0
|
||||
let finite = best < big
|
||||
print(` rgba (clamped/100): {fixed(Math.min(buf[o], big) / 100.0)} {fixed(Math.min(buf[o + 1], big) / 100.0)} {fixed(Math.min(buf[o + 2], big) / 100.0)} {fixed(Math.min(buf[o + 3], big))} finite {finite} bits {buf[o]}`)
|
||||
free(buf)
|
||||
}
|
||||
# Debug: write a 2D texture's level 0 (RGBA8, alpha dropped) as a binary PPM.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue