fix(Gargantua): setup_camera 改用 V3 值语义(消除旧版 &_g_cam 指针残留),移除定位用调试输出
This commit is contained in:
1 parent
d9b39e99a5
commit
befed3904a
1 file changed
+115
-142
+115
-142
@@ -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
|
||||
|
||||
Reference in new issue
Block a user