From befed3904acd46e1dcef48f691d58a41d5330866 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 16 Oct 2026 14:12:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(Gargantua):=20setup=5Fcamera=20=E6=94=B9?= =?UTF-8?q?=E7=94=A8=20V3=20=E5=80=BC=E8=AF=AD=E4=B9=89=EF=BC=88=E6=B6=88?= =?UTF-8?q?=E9=99=A4=E6=97=A7=E7=89=88=20&=5Fg=5Fcam=20=E6=8C=87=E9=92=88?= =?UTF-8?q?=E6=AE=8B=E7=95=99=EF=BC=89=EF=BC=8C=E7=A7=BB=E9=99=A4=E5=AE=9A?= =?UTF-8?q?=E4=BD=8D=E7=94=A8=E8=B0=83=E8=AF=95=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/Gargantua/main.vp | 257 ++++++++++++++++++----------------------- 1 file changed, 115 insertions(+), 142 deletions(-) diff --git a/Apps/Gargantua/main.vp b/Apps/Gargantua/main.vp index 5e0caef..17e0ec9 100644 --- a/Apps/Gargantua/main.vp +++ b/Apps/Gargantua/main.vp @@ -1,14 +1,12 @@ import vpsdk.window as window import vpsdk.process as process import vpsdk.vpui as vpui -import vpsdk.stdlib as stdlib import vpsdk.stdio as stdio import string -import vipermath as vm -import viperlib +import math as vm from stdint import * import memhub -import t, c + define GW = 160 define GH = 90 @@ -25,122 +23,97 @@ define YIELD_ROWS = 4 define V3_POOL_SIZE = 8192 define V3_POOL_BYTES = V3_POOL_SIZE * 24 + 512 -_v3_mem: t.CArray[uint8, V3_POOL_BYTES] +_v3_mem: [V3_POOL_BYTES]uint8 _v3_pool: memhub.MemPool* -_fb_mem: t.CArray[uint32, GW * GH] +_fb_mem: [GW * GH]uint32 class V3: - x: t.CFloat64T - y: t.CFloat64T - z: t.CFloat64T + x: double + y: double + z: double - def __new__() -> V3*: - return V3*(_v3_pool.alloc(24)) - - def __init__(self, x: t.CFloat64T, y: t.CFloat64T, z: t.CFloat64T): + def __init__(self, x: double, y: double, z: double): self.x = x self.y = y self.z = z - def __add__(self, b: V3*) -> V3*: + def __add__(self, b: V3) -> V3: return V3(self.x + b.x, self.y + b.y, self.z + b.z) - def __sub__(self, b: V3*) -> V3*: + def __sub__(self, b: V3) -> V3: return V3(self.x - b.x, self.y - b.y, self.z - b.z) - def __mul__(self, s: t.CFloat64T) -> V3*: + def __mul__(self, s: double) -> V3: return V3(self.x * s, self.y * s, self.z * s) - def __neg__(self) -> V3*: + def __neg__(self) -> V3: return V3(-self.x, -self.y, -self.z) - def dot(self, b: V3*) -> t.CFloat64T: + def dot(self, b: V3) -> double: return self.x * b.x + self.y * b.y + self.z * b.z - def cross(self, b: V3*) -> V3*: + def cross(self, b: V3) -> V3: return V3(self.y * b.z - self.z * b.y, self.z * b.x - self.x * b.z, self.x * b.y - self.y * b.x) - def nrm(self) -> V3*: - l: t.CFloat64T = vm.sqrt(self.dot(self)) + def nrm(self) -> V3: + l: double = vm.sqrt(self.dot(self)) if l > 1e-12: return self * (1.0 / l) return V3(0.0, 0.0, 0.0) - def lerp(self, b: V3*, t_val: t.CFloat64T) -> V3*: + def lerp(self, b: V3, t_val: double) -> V3: return self * (1.0 - t_val) + b * t_val -_g_cam: t.CArray[t.CFloat64T, 3] -_g_fwd: t.CArray[t.CFloat64T, 3] -_g_right: t.CArray[t.CFloat64T, 3] -_g_up: t.CArray[t.CFloat64T, 3] - -CAM: V3* -FWD: V3* -RIGHT: V3* -UP: V3* +CAM: V3 +FWD: V3 +RIGHT: V3 +UP: V3 def v3_pool_reset(): _v3_pool.reset() -def clmp(x: t.CFloat64T, a: t.CFloat64T, b: t.CFloat64T) -> t.CFloat64T: +def clmp(x: double, a: double, b: double) -> double: if x < a: return a if x > b: return b return x -def smoothstep(a: t.CFloat64T, b: t.CFloat64T, x: t.CFloat64T) -> t.CFloat64T: - t_val: t.CFloat64T = clmp((x - a) / (b - a), 0.0, 1.0) +def smoothstep(a: double, b: double, x: double) -> double: + t_val: double = clmp((x - a) / (b - a), 0.0, 1.0) return t_val * t_val * (3.0 - 2.0 * t_val) def setup_camera(): global CAM, FWD, RIGHT, UP - e: t.CFloat64T = CAM_ELEV * 3.14159265358979323846 / 180.0 - CAM = &_g_cam - CAM.x = CAM_DIST * vm.cos(e) - CAM.y = CAM_DIST * vm.sin(e) - CAM.z = 0.0 - tmp0: V3* = V3(0.0, 0.0, 0.0) - FWD = &_g_fwd - tmp1: V3* = tmp0 - CAM - n1: V3* = tmp1.nrm() - FWD.x = n1.x - FWD.y = n1.y - FWD.z = n1.z - tmp2: V3* = V3(0.0, 1.0, 0.0) - RIGHT = &_g_right - tmp3: V3* = FWD.cross(tmp2) - tmp4: V3* = tmp3.nrm() - RIGHT.x = tmp4.x - RIGHT.y = tmp4.y - RIGHT.z = tmp4.z - UP = &_g_up - tmp5: V3* = RIGHT.cross(FWD) - UP.x = tmp5.x - UP.y = tmp5.y - UP.z = tmp5.z + e: double = CAM_ELEV * 3.14159265358979323846 / 180.0 + CAM = V3(CAM_DIST * vm.cos(e), CAM_DIST * vm.sin(e), 0.0) + tmp0: V3 = V3(0.0, 0.0, 0.0) + FWD = (tmp0 - CAM).nrm() + tmp2: V3 = V3(0.0, 1.0, 0.0) + RIGHT = FWD.cross(tmp2).nrm() + UP = RIGHT.cross(FWD) -def hash3(x: t.CFloat64T, y: t.CFloat64T, z: t.CFloat64T) -> t.CFloat64T: - n: t.CFloat64T = vm.sin(x * 127.1 + y * 311.7 + z * 74.7) * 43758.5453 +def hash3(x: double, y: double, z: double) -> double: + n: double = vm.sin(x * 127.1 + y * 311.7 + z * 74.7) * 43758.5453 return n - vm.floor(n) -def stars(d: V3*) -> V3*: - col: V3* = V3(0.0, 0.0, 0.0) +def stars(d: V3) -> V3: + col: V3 = V3(0.0, 0.0, 0.0) for i in range(3): - s: t.CFloat64T = 80.0 + t.CFloat64T(i) * 90.0 - px: t.CFloat64T = d.x * s - py: t.CFloat64T = d.y * s - pz: t.CFloat64T = d.z * s - ix: t.CFloat64T = vm.floor(px) - iy: t.CFloat64T = vm.floor(py) - iz: t.CFloat64T = vm.floor(pz) - h: t.CFloat64T = hash3(ix, iy, iz) + s: double = 80.0 + double(i) * 90.0 + px: double = d.x * s + py: double = d.y * s + pz: double = d.z * s + ix: double = vm.floor(px) + iy: double = vm.floor(py) + iz: double = vm.floor(pz) + h: double = hash3(ix, iy, iz) if h > 0.991: - fx: t.CFloat64T = px - ix - 0.5 - fy: t.CFloat64T = py - iy - 0.5 - fz: t.CFloat64T = pz - iz - 0.5 - d2: t.CFloat64T = fx * fx + fy * fy + fz * fz - br: t.CFloat64T = (h - 0.991) / 0.009 * vm.exp(-d2 * 9.0) * 1.4 - tv: t.CFloat64T = hash3(iy, iz, ix) - tint: V3* = V3(0.0, 0.0, 0.0) + fx: double = px - ix - 0.5 + fy: double = py - iy - 0.5 + fz: double = pz - iz - 0.5 + d2: double = fx * fx + fy * fy + fz * fz + br: double = (h - 0.991) / 0.009 * vm.exp(-d2 * 9.0) * 1.4 + tv: double = hash3(iy, iz, ix) + tint: V3 = V3(0.0, 0.0, 0.0) if tv < 0.3: tint = V3(0.7, 0.8, 1.0) elif tv > 0.8: @@ -150,82 +123,82 @@ def stars(d: V3*) -> V3*: col = col + tint * br return col -def disk_shade(cp: V3*, rr: t.CFloat64T, gT: t.CFloat64T) -> V3*: - tt: t.CFloat64T = (rr - DISK_IN) / (DISK_OUT - DISK_IN) - edge: t.CFloat64T = smoothstep(0.0, 0.07, tt) * smoothstep(0.0, 0.18, 1.0 - tt) - ang: t.CFloat64T = vm.atan2(cp.z, cp.x) - w: t.CFloat64T = 1.0 / vm.pow(rr, 1.5) - ph: t.CFloat64T = ang - gT * 0.0011 * w * 9.0 - n: t.CFloat64T = 0.5 + 0.5 * vm.sin(ph * 5.0 - rr * 1.6) - n2: t.CFloat64T = 0.5 + 0.5 * vm.sin(ph * 13.0 + rr * 0.8 + 1.7) - dens: t.CFloat64T = (0.35 + 0.65 * n) * (0.55 + 0.45 * n2) - bright: t.CFloat64T = (0.45 + 1.7 * vm.pow(1.0 - tt, 1.8)) * edge - vdir: V3* = V3(-cp.z, 0.0, cp.x).nrm() - beta: t.CFloat64T = 0.46 / vm.sqrt(rr) - to_cam: V3* = (CAM - cp).nrm() - mu: t.CFloat64T = vdir.dot(to_cam) - dop: t.CFloat64T = 1.0 / (1.0 - beta * mu) - beam: t.CFloat64T = vm.pow(dop, 3.0) - c1: V3* = V3(1.0, 0.92, 0.68) - c2: V3* = V3(1.0, 0.42, 0.13) - base: V3* = c1.lerp(c2, tt) +def disk_shade(cp: V3, rr: double, gT: double) -> V3: + tt: double = (rr - DISK_IN) / (DISK_OUT - DISK_IN) + edge: double = smoothstep(0.0, 0.07, tt) * smoothstep(0.0, 0.18, 1.0 - tt) + ang: double = vm.atan2(cp.z, cp.x) + w: double = 1.0 / vm.pow(rr, 1.5) + ph: double = ang - gT * 0.0011 * w * 9.0 + n: double = 0.5 + 0.5 * vm.sin(ph * 5.0 - rr * 1.6) + n2: double = 0.5 + 0.5 * vm.sin(ph * 13.0 + rr * 0.8 + 1.7) + dens: double = (0.35 + 0.65 * n) * (0.55 + 0.45 * n2) + bright: double = (0.45 + 1.7 * vm.pow(1.0 - tt, 1.8)) * edge + vdir: V3 = V3(-cp.z, 0.0, cp.x).nrm() + beta: double = 0.46 / vm.sqrt(rr) + to_cam: V3 = (CAM - cp).nrm() + mu: double = vdir.dot(to_cam) + dop: double = 1.0 / (1.0 - beta * mu) + beam: double = vm.pow(dop, 3.0) + c1: V3 = V3(1.0, 0.92, 0.68) + c2: V3 = V3(1.0, 0.42, 0.13) + base: V3 = c1.lerp(c2, tt) base.z += (dop - 1.0) * 0.35 base.x -= (dop - 1.0) * 0.05 - inten: t.CFloat64T = bright * dens * beam * 1.25 + inten: double = bright * dens * beam * 1.25 return base * inten -def trace(dir_v: V3*, gT: t.CFloat64T) -> V3*: +def trace(dir_v: V3, gT: double) -> V3: v3_pool_reset() - pos: V3* = V3(CAM.x, CAM.y, CAM.z) - vel: V3* = V3(dir_v.x, dir_v.y, dir_v.z) - hvec: V3* = pos.cross(vel) - h2: t.CFloat64T = hvec.dot(hvec) - T: t.CFloat64T = 1.0 - col: V3* = V3(0.0, 0.0, 0.0) + pos: V3 = V3(CAM.x, CAM.y, CAM.z) + vel: V3 = V3(dir_v.x, dir_v.y, dir_v.z) + hvec: V3 = pos.cross(vel) + h2: double = hvec.dot(hvec) + T: double = 1.0 + col: V3 = V3(0.0, 0.0, 0.0) for i in range(MAX_STEPS): - r2: t.CFloat64T = pos.dot(pos) - r: t.CFloat64T = vm.sqrt(r2) + r2: double = pos.dot(pos) + r: double = vm.sqrt(r2) if r < 1.0: break if r > ESCAPE_R: col = col + stars(vel.nrm()) * T break - dt: t.CFloat64T = clmp(r * 0.08, 0.03, 2.2) - r5: t.CFloat64T = vm.pow(r2, 2.5) - coeff: t.CFloat64T = -1.5 * h2 / r5 + dt: double = clmp(r * 0.08, 0.03, 2.2) + r5: double = vm.pow(r2, 2.5) + coeff: double = -1.5 * h2 / r5 - k1v: V3* = pos * coeff - k2p_a: V3* = vel + k1v * (dt * 0.5) - k2v_a: V3* = pos + vel * (dt * 0.5) - r2_a: t.CFloat64T = k2v_a.dot(k2v_a) - coeff_a: t.CFloat64T = -1.5 * h2 / vm.pow(r2_a, 2.5) - k2v: V3* = k2v_a * coeff_a + k1v: V3 = pos * coeff + k2p_a: V3 = vel + k1v * (dt * 0.5) + k2v_a: V3 = pos + vel * (dt * 0.5) + r2_a: double = k2v_a.dot(k2v_a) + coeff_a: double = -1.5 * h2 / vm.pow(r2_a, 2.5) + k2v: V3 = k2v_a * coeff_a - k3p_a: V3* = vel + k2v * (dt * 0.5) - k3v_a: V3* = pos + k2p_a * (dt * 0.5) - r2_b: t.CFloat64T = k3v_a.dot(k3v_a) - coeff_b: t.CFloat64T = -1.5 * h2 / vm.pow(r2_b, 2.5) - k3v: V3* = k3v_a * coeff_b + k3p_a: V3 = vel + k2v * (dt * 0.5) + k3v_a: V3 = pos + k2p_a * (dt * 0.5) + r2_b: double = k3v_a.dot(k3v_a) + coeff_b: double = -1.5 * h2 / vm.pow(r2_b, 2.5) + k3v: V3 = k3v_a * coeff_b - k4p_a: V3* = vel + k3v * dt - k4v_a: V3* = pos + k3p_a * dt - r2_c: t.CFloat64T = k4v_a.dot(k4v_a) - coeff_c: t.CFloat64T = -1.5 * h2 / vm.pow(r2_c, 2.5) - k4v: V3* = k4v_a * coeff_c + k4p_a: V3 = vel + k3v * dt + k4v_a: V3 = pos + k3p_a * dt + r2_c: double = k4v_a.dot(k4v_a) + coeff_c: double = -1.5 * h2 / vm.pow(r2_c, 2.5) + k4v: V3 = k4v_a * coeff_c - npos: V3* = pos + (vel + k2p_a * 2.0 + k3p_a * 2.0 + k4p_a) * (dt / 6.0) - nvel: V3* = vel + (k1v + k2v * 2.0 + k3v * 2.0 + k4v) * (dt / 6.0) + npos: V3 = pos + (vel + k2p_a * 2.0 + k3p_a * 2.0 + k4p_a) * (dt / 6.0) + nvel: V3 = vel + (k1v + k2v * 2.0 + k3v * 2.0 + k4v) * (dt / 6.0) if pos.y * npos.y < 0.0: - f: t.CFloat64T = pos.y / (pos.y - npos.y) - cp: V3* = pos.lerp(npos, f) - rr: t.CFloat64T = vm.sqrt(cp.x * cp.x + cp.z * cp.z) + f: double = pos.y / (pos.y - npos.y) + cp: V3 = pos.lerp(npos, f) + rr: double = vm.sqrt(cp.x * cp.x + cp.z * cp.z) if rr > DISK_IN and rr < DISK_OUT: - emit: V3* = disk_shade(cp, rr, gT) + emit: V3 = disk_shade(cp, rr, gT) col = col + emit * T - a: t.CFloat64T = clmp(smoothstep(0.0, 0.07, (rr - DISK_IN) / (DISK_OUT - DISK_IN)) * smoothstep(0.0, 0.18, 1.0 - (rr - DISK_IN) / (DISK_OUT - DISK_IN)) * 0.92, 0.0, 1.0) + a: double = clmp(smoothstep(0.0, 0.07, (rr - DISK_IN) / (DISK_OUT - DISK_IN)) * smoothstep(0.0, 0.18, 1.0 - (rr - DISK_IN) / (DISK_OUT - DISK_IN)) * 0.92, 0.0, 1.0) T = T * (1.0 - a) if T < 0.01: break @@ -234,13 +207,13 @@ def trace(dir_v: V3*, gT: t.CFloat64T) -> V3*: vel = nvel return col -def shade_pixel(px: int, py: int, gT: t.CFloat64T) -> uint32: - aspect: t.CFloat64T = GW_F / GH_F - sx: t.CFloat64T = (2.0 * (t.CFloat64T(px) + 0.5) / GW_F - 1.0) * aspect * FOVF - sy: t.CFloat64T = (1.0 - 2.0 * (t.CFloat64T(py) + 0.5) / GH_F) * FOVF - dir_v: V3* = (FWD + RIGHT * sx + UP * sy).nrm() - c: V3* = trace(dir_v, gT) - ex: t.CFloat64T = 1.15 +def shade_pixel(px: int, py: int, gT: double) -> uint32: + aspect: double = GW_F / GH_F + sx: double = (2.0 * (double(px) + 0.5) / GW_F - 1.0) * aspect * FOVF + sy: double = (1.0 - 2.0 * (double(py) + 0.5) / GH_F) * FOVF + dir_v: V3 = (FWD + RIGHT * sx + UP * sy).nrm() + c: V3 = trace(dir_v, gT) + ex: double = 1.15 c = c * ex c.x = c.x / (1.0 + c.x) c.y = c.y / (1.0 + c.y) @@ -253,8 +226,8 @@ def shade_pixel(px: int, py: int, gT: t.CFloat64T) -> uint32: B: int = int(clmp(c.z, 0.0, 1.0) * 255.0) return uint32((R << 16) | (G << 8) | B) -@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16)) -def _start() -> int | t.CExport: +@__attribute__(section(".text.startup"), aligned(16)) +export def _start() -> int: global _v3_pool _v3_pool = memhub.MemPool(&_v3_mem, V3_POOL_BYTES) setup_camera() @@ -274,7 +247,7 @@ def _start() -> int | t.CExport: root.geometry(100, 30, GW, GH + 32) - gT: t.CFloat64T = 0.0 + gT: double = 0.0 rendered: int = 0 evt: window.InputEvent