improve sw renderer
This commit is contained in:
parent
415d424057
commit
39ee0fefb7
89 changed files with 9380 additions and 2307 deletions
287
demo/mod/sky.fnl
287
demo/mod/sky.fnl
|
|
@ -1,23 +1,32 @@
|
|||
(local ffi (require :ffi))
|
||||
(local pxl8 (require :pxl8))
|
||||
(local effects (require :pxl8.effects))
|
||||
|
||||
(local SKY_GRADIENT_START 144)
|
||||
(local SKY_GRADIENT_COUNT 16)
|
||||
(local sky-radius 900)
|
||||
(local sky-segments 16)
|
||||
(local sky-rings 16)
|
||||
(local max-theta (* math.pi 0.55))
|
||||
|
||||
(local STAR_COUNT 200)
|
||||
(local TINY_STAR_COUNT 5000)
|
||||
(local STAR_SILVER_START 160)
|
||||
(local STAR_BLUE_START 168)
|
||||
(local STAR_RED_START 176)
|
||||
(local NUM_RANDOM_STARS 300)
|
||||
(local NUM_TINY_STARS 7000)
|
||||
(local STAR_SEED 0xDEADBEEF)
|
||||
(local STAR_CYCLE_PERIOD 7200)
|
||||
|
||||
;; Use existing bright palette colors
|
||||
;; Silver/white: indices 14-15 (brightest grays)
|
||||
(local IDX_SILVER 14)
|
||||
;; Warm/torch: indices 216-218 (bright creams/yellows)
|
||||
(local IDX_TORCH 216)
|
||||
;; Blue/magic: indices 176-178 (purples - brightest of the range)
|
||||
(local IDX_MAGIC 176)
|
||||
|
||||
(var sky-mesh nil)
|
||||
(var last-gradient-key nil)
|
||||
(var stars [])
|
||||
(var random-stars [])
|
||||
(var sky-mesh nil)
|
||||
(var star-count 0)
|
||||
(var star-directions nil)
|
||||
(var star-glows nil)
|
||||
(var star-projected nil)
|
||||
(var star-time 0)
|
||||
(var tiny-stars [])
|
||||
|
||||
(fn generate-sky-gradient [zenith-r zenith-g zenith-b horizon-r horizon-g horizon-b]
|
||||
|
|
@ -33,8 +42,8 @@
|
|||
indices []]
|
||||
|
||||
(for [i 0 (- sky-rings 1)]
|
||||
(let [theta0 (* (/ i sky-rings) max-theta)
|
||||
theta1 (* (/ (+ i 1) sky-rings) max-theta)
|
||||
(let [theta0 (* (/ i sky-rings) math.pi 0.5)
|
||||
theta1 (* (/ (+ i 1) sky-rings) math.pi 0.5)
|
||||
sin-t0 (math.sin theta0)
|
||||
cos-t0 (math.cos theta0)
|
||||
sin-t1 (math.sin theta1)
|
||||
|
|
@ -67,22 +76,17 @@
|
|||
|
||||
(if (= i 0)
|
||||
(do
|
||||
;; First ring is degenerate - just a triangle from pole
|
||||
;; Vertices: v00 (pole, c0), v11 (bottom-right, c1), v10 (bottom-left, c1)
|
||||
(table.insert verts {:x x00 :y y0 :z z00 :nx nx00 :ny ny00 :nz nz00 :color c0 :light 255})
|
||||
(table.insert verts {:x x11 :y y1 :z z11 :nx nx11 :ny ny11 :nz nz11 :color c1 :light 255})
|
||||
(table.insert verts {:x x10 :y y1 :z z10 :nx nx10 :ny ny10 :nz nz10 :color c1 :light 255})
|
||||
;; Triangle: base, base+2, base+1
|
||||
(table.insert indices base-idx)
|
||||
(table.insert indices (+ base-idx 2))
|
||||
(table.insert indices (+ base-idx 1)))
|
||||
(do
|
||||
;; Regular quad: v00 (top-left), v01 (top-right), v11 (bottom-right), v10 (bottom-left)
|
||||
(table.insert verts {:x x00 :y y0 :z z00 :nx nx00 :ny ny00 :nz nz00 :color c0 :light 255})
|
||||
(table.insert verts {:x x01 :y y0 :z z01 :nx nx01 :ny ny01 :nz nz01 :color c0 :light 255})
|
||||
(table.insert verts {:x x11 :y y1 :z z11 :nx nx11 :ny ny11 :nz nz11 :color c1 :light 255})
|
||||
(table.insert verts {:x x10 :y y1 :z z10 :nx nx10 :ny ny10 :nz nz10 :color c1 :light 255})
|
||||
;; push_quad(base, base+3, base+2, base+1) = triangles (base,base+3,base+2) and (base,base+2,base+1)
|
||||
(table.insert indices base-idx)
|
||||
(table.insert indices (+ base-idx 3))
|
||||
(table.insert indices (+ base-idx 2))
|
||||
|
|
@ -98,149 +102,142 @@
|
|||
(generate-sky-gradient zenith-r zenith-g zenith-b horizon-r horizon-g horizon-b)
|
||||
(set last-gradient-key key))))
|
||||
|
||||
(fn palette-ramp [start c0 c1]
|
||||
(let [r0 (bit.rshift (bit.band c0 0xFF0000) 16)
|
||||
g0 (bit.rshift (bit.band c0 0x00FF00) 8)
|
||||
b0 (bit.band c0 0x0000FF)
|
||||
r1 (bit.rshift (bit.band c1 0xFF0000) 16)
|
||||
g1 (bit.rshift (bit.band c1 0x00FF00) 8)
|
||||
b1 (bit.band c1 0x0000FF)]
|
||||
(for [i 0 7]
|
||||
(let [t (/ i 7)
|
||||
r (math.floor (+ r0 (* t (- r1 r0))))
|
||||
g (math.floor (+ g0 (* t (- g1 g0))))
|
||||
b (math.floor (+ b0 (* t (- b1 b0))))]
|
||||
(pxl8.set_palette_rgb (+ start i) r g b)))))
|
||||
(fn galactic-band-factor [dx dy dz]
|
||||
(let [band-len (math.sqrt (+ (* 0.6 0.6) (* 0.3 0.3) (* 0.742 0.742)))
|
||||
bx (/ 0.6 band-len)
|
||||
by (/ 0.3 band-len)
|
||||
bz (/ 0.742 band-len)
|
||||
dist-from-band (math.abs (+ (* dx bx) (* dy by) (* dz bz)))
|
||||
in-band (- 1 (math.min (* dist-from-band 3) 1))]
|
||||
(* in-band in-band)))
|
||||
|
||||
(fn init-star-palette []
|
||||
(palette-ramp STAR_SILVER_START 0x707888 0xFFFFFF) ;; silver
|
||||
(palette-ramp STAR_BLUE_START 0x5070B0 0xD0E8FF) ;; blue
|
||||
(palette-ramp STAR_RED_START 0x802020 0xFF9090)) ;; red
|
||||
|
||||
(fn generate-stars [seed]
|
||||
(set stars [])
|
||||
(fn generate-stars []
|
||||
(set random-stars [])
|
||||
(set tiny-stars [])
|
||||
(init-star-palette)
|
||||
(pxl8.rng_seed seed)
|
||||
|
||||
(for [i 1 STAR_COUNT]
|
||||
(let [theta (math.acos (- 1 (* (pxl8.rng_f32) 0.85)))
|
||||
phi (* (pxl8.rng_f32) math.pi 2)
|
||||
brightness (pxl8.rng_range 1 4)
|
||||
color-type (pxl8.rng_range 0 100)
|
||||
shade (pxl8.rng_range 0 5)
|
||||
color (if (< color-type 3) (+ STAR_RED_START shade)
|
||||
(< color-type 15) (+ STAR_BLUE_START shade)
|
||||
(+ STAR_SILVER_START shade))
|
||||
sin-t (math.sin theta)
|
||||
cos-t (math.cos theta)]
|
||||
(table.insert stars {:dx (* sin-t (math.cos phi))
|
||||
:dy cos-t
|
||||
:dz (* sin-t (math.sin phi))
|
||||
:brightness brightness
|
||||
:color color})))
|
||||
;; Generate random stars - use full upper hemisphere (dy > -0.1)
|
||||
(for [i 0 (- NUM_RANDOM_STARS 1)]
|
||||
(let [h1 (pxl8.hash32 (+ STAR_SEED (* i 5)))
|
||||
h2 (pxl8.hash32 (+ STAR_SEED (* i 5) 1))
|
||||
h3 (pxl8.hash32 (+ STAR_SEED (* i 5) 2))
|
||||
h4 (pxl8.hash32 (+ STAR_SEED (* i 5) 3))
|
||||
theta (* (/ h1 0xFFFFFFFF) math.pi 2)
|
||||
phi (math.acos (- 1 (* (/ h2 0xFFFFFFFF) 1.0)))
|
||||
sin-phi (math.sin phi)
|
||||
cos-phi (math.cos phi)
|
||||
dx (* sin-phi (math.cos theta))
|
||||
dy cos-phi
|
||||
dz (* sin-phi (math.sin theta))
|
||||
brightness-raw (/ (% h3 256) 255)
|
||||
brightness (math.floor (+ 60 (* brightness-raw brightness-raw 195)))
|
||||
color-type (% h4 100)
|
||||
color (if (< color-type 8) (+ IDX_TORCH (% (bit.rshift h4 8) 2))
|
||||
(< color-type 16) (+ IDX_MAGIC (% (bit.rshift h4 8) 2))
|
||||
(+ IDX_SILVER (% (bit.rshift h4 8) 2)))]
|
||||
|
||||
(pxl8.rng_seed (+ seed 0xCAFEBABE))
|
||||
(for [i 1 TINY_STAR_COUNT]
|
||||
(let [theta (math.acos (- 1 (* (pxl8.rng_f32) 0.95)))
|
||||
phi (* (pxl8.rng_f32) math.pi 2)
|
||||
brightness (+ 25 (pxl8.rng_range 0 40))
|
||||
shade (pxl8.rng_range 0 3)
|
||||
color-type (pxl8.rng_range 0 100)
|
||||
color (if (< color-type 15) (+ STAR_BLUE_START shade)
|
||||
(+ STAR_SILVER_START shade))
|
||||
sin-t (math.sin theta)
|
||||
cos-t (math.cos theta)]
|
||||
(table.insert tiny-stars {:dx (* sin-t (math.cos phi))
|
||||
:dy cos-t
|
||||
:dz (* sin-t (math.sin phi))
|
||||
:brightness brightness
|
||||
:color color}))))
|
||||
(when (> dy -0.1)
|
||||
(table.insert random-stars {:dx dx :dy dy :dz dz
|
||||
:brightness brightness
|
||||
:color color}))))
|
||||
|
||||
(fn project-direction [dir-x dir-y dir-z yaw pitch width height]
|
||||
(let [cos-yaw (math.cos yaw)
|
||||
sin-yaw (math.sin yaw)
|
||||
cos-pitch (math.cos pitch)
|
||||
sin-pitch (math.sin pitch)
|
||||
rotated-x (+ (* dir-x cos-yaw) (* dir-z sin-yaw))
|
||||
rotated-z (+ (* (- dir-x) sin-yaw) (* dir-z cos-yaw))
|
||||
rotated-y (- (* dir-y cos-pitch) (* rotated-z sin-pitch))
|
||||
final-z (+ (* dir-y sin-pitch) (* rotated-z cos-pitch))]
|
||||
(when (> final-z 0.01)
|
||||
(let [fov 1.047
|
||||
aspect (/ width height)
|
||||
half-fov-tan (math.tan (* fov 0.5))
|
||||
ndc-x (/ rotated-x (* final-z half-fov-tan aspect))
|
||||
ndc-y (/ rotated-y (* final-z half-fov-tan))]
|
||||
(when (and (>= ndc-x -1) (<= ndc-x 1) (>= ndc-y -1) (<= ndc-y 1))
|
||||
{:x (math.floor (* (+ 1 ndc-x) 0.5 width))
|
||||
:y (math.floor (* (- 1 ndc-y) 0.5 height))})))))
|
||||
(let [tiny-seed (+ STAR_SEED 0xCAFEBABE)]
|
||||
(for [i 0 (- NUM_TINY_STARS 1)]
|
||||
(let [h1 (pxl8.hash32 (+ tiny-seed (* i 4)))
|
||||
h2 (pxl8.hash32 (+ tiny-seed (* i 4) 1))
|
||||
h3 (pxl8.hash32 (+ tiny-seed (* i 4) 2))
|
||||
h4 (pxl8.hash32 (+ tiny-seed (* i 4) 3))
|
||||
theta (* (/ h1 0xFFFFFFFF) math.pi 2)
|
||||
phi (math.acos (- 1 (* (/ h2 0xFFFFFFFF) 1.0)))
|
||||
sin-phi (math.sin phi)
|
||||
cos-phi (math.cos phi)
|
||||
dx (* sin-phi (math.cos theta))
|
||||
dy cos-phi
|
||||
dz (* sin-phi (math.sin theta))
|
||||
band-boost (galactic-band-factor dx dy dz)
|
||||
base-bright (+ 40 (% h3 50))
|
||||
brightness (+ base-bright (math.floor (* band-boost 40)))
|
||||
color-shift (% h4 100)
|
||||
color (if (< color-shift 3) (+ IDX_TORCH (% (bit.rshift h4 8) 2))
|
||||
(< color-shift 12) (+ IDX_MAGIC (% (bit.rshift h4 8) 2))
|
||||
(+ IDX_SILVER (% (bit.rshift h4 8) 2)))]
|
||||
(when (> dy -0.1)
|
||||
(table.insert tiny-stars {:dx dx :dy dy :dz dz
|
||||
:brightness brightness
|
||||
:color color})))))
|
||||
|
||||
(fn render-stars [yaw pitch intensity]
|
||||
(when (> intensity 0)
|
||||
(let [width (pxl8.get_width)
|
||||
height (pxl8.get_height)
|
||||
glows []
|
||||
fade-sq (* intensity intensity)]
|
||||
(set star-count (+ (length tiny-stars) (length random-stars)))
|
||||
(set star-directions (pxl8.create_vec3_array star-count))
|
||||
(set star-glows (pxl8.create_glows 10000))
|
||||
(set star-projected (pxl8.create_vec3_array star-count))
|
||||
|
||||
(each [_ star (ipairs tiny-stars)]
|
||||
(let [screen (project-direction star.dx star.dy star.dz yaw pitch width height)]
|
||||
(when screen
|
||||
(let [int (math.floor (* star.brightness fade-sq))]
|
||||
(var idx 0)
|
||||
(each [_ star (ipairs tiny-stars)]
|
||||
(let [dir (. star-directions idx)]
|
||||
(set dir.x star.dx)
|
||||
(set dir.y star.dy)
|
||||
(set dir.z star.dz))
|
||||
(set idx (+ idx 1)))
|
||||
(each [_ star (ipairs random-stars)]
|
||||
(let [dir (. star-directions idx)]
|
||||
(set dir.x star.dx)
|
||||
(set dir.y star.dy)
|
||||
(set dir.z star.dz))
|
||||
(set idx (+ idx 1))))
|
||||
|
||||
(fn render-stars [cam-x cam-y cam-z intensity dt]
|
||||
(set star-time (+ star-time (or dt 0)))
|
||||
(when (and (> intensity 0) (> star-count 0) star-glows)
|
||||
(let [fade-in (* intensity intensity)
|
||||
time-factor (/ star-time 60)
|
||||
star-rotation (/ (* star-time math.pi 2) STAR_CYCLE_PERIOD)
|
||||
t (pxl8.mat4_translate cam-x cam-y cam-z)
|
||||
r (pxl8.mat4_rotate_y star-rotation)
|
||||
s (pxl8.mat4_scale sky-radius sky-radius sky-radius)
|
||||
transform (pxl8.mat4_multiply t (pxl8.mat4_multiply r s))
|
||||
tiny-count (length tiny-stars)]
|
||||
|
||||
(star-glows:clear)
|
||||
(pxl8.project_points star-directions star-projected star-count transform)
|
||||
|
||||
(for [i 0 (- tiny-count 1)]
|
||||
(let [screen (. star-projected i)]
|
||||
(when (> screen.z 0)
|
||||
(let [star (. tiny-stars (+ i 1))
|
||||
int (math.floor (* star.brightness fade-in))]
|
||||
(when (> int 8)
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 1
|
||||
:intensity int
|
||||
:color star.color
|
||||
:shape effects.GLOW_CIRCLE}))))))
|
||||
(star-glows:add (math.floor screen.x) (math.floor screen.y)
|
||||
1 int star.color pxl8.GLOW_CIRCLE))))))
|
||||
|
||||
(each [_ star (ipairs stars)]
|
||||
(let [screen (project-direction star.dx star.dy star.dz yaw pitch width height)]
|
||||
(when screen
|
||||
(let [base-int (math.floor (* star.brightness 50 fade-sq 1.5))]
|
||||
(if (>= star.brightness 4)
|
||||
(for [i 0 (- (length random-stars) 1)]
|
||||
(let [screen (. star-projected (+ tiny-count i))]
|
||||
(when (> screen.z 0)
|
||||
(let [star (. random-stars (+ i 1))
|
||||
phase (+ (* (+ i 1) 2.137) (* time-factor 3.0))
|
||||
twinkle (+ 0.75 (* 0.25 (math.sin (* phase 6.28))))
|
||||
int (math.floor (* star.brightness fade-in twinkle))
|
||||
sx (math.floor screen.x)
|
||||
sy (math.floor screen.y)]
|
||||
(if (> star.brightness 220)
|
||||
(do
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 4
|
||||
:intensity (math.floor (/ base-int 4))
|
||||
:color star.color
|
||||
:shape effects.GLOW_CIRCLE})
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 2
|
||||
:intensity base-int
|
||||
:color star.color
|
||||
:shape effects.GLOW_DIAMOND}))
|
||||
(>= star.brightness 3)
|
||||
(star-glows:add sx sy 3 (math.floor (* int 1.5)) star.color pxl8.GLOW_DIAMOND)
|
||||
(star-glows:add sx sy 5 (math.floor (/ int 2)) star.color pxl8.GLOW_CIRCLE))
|
||||
(> star.brightness 180)
|
||||
(do
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 3
|
||||
:intensity (math.floor (/ base-int 4))
|
||||
:color star.color
|
||||
:shape effects.GLOW_CIRCLE})
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 2
|
||||
:intensity base-int
|
||||
:color star.color
|
||||
:shape effects.GLOW_DIAMOND}))
|
||||
(>= star.brightness 2)
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 2
|
||||
:intensity base-int
|
||||
:color star.color
|
||||
:shape effects.GLOW_DIAMOND})
|
||||
(table.insert glows {:x screen.x :y screen.y
|
||||
:radius 1
|
||||
:intensity (math.floor (* base-int 0.7))
|
||||
:color star.color
|
||||
:shape effects.GLOW_CIRCLE}))))))
|
||||
(star-glows:add sx sy 2 int star.color pxl8.GLOW_DIAMOND)
|
||||
(star-glows:add sx sy 4 (math.floor (/ int 3)) star.color pxl8.GLOW_CIRCLE))
|
||||
(> star.brightness 120)
|
||||
(do
|
||||
(star-glows:add sx sy 2 (math.floor (* int 0.67)) star.color pxl8.GLOW_DIAMOND)
|
||||
(star-glows:add sx sy 3 (math.floor (/ int 4)) star.color pxl8.GLOW_CIRCLE))
|
||||
(star-glows:add sx sy 2 (math.floor (* int 0.5)) star.color pxl8.GLOW_CIRCLE))))))
|
||||
|
||||
(when (> (length glows) 0)
|
||||
(effects.glows glows)))))
|
||||
(when (> (star-glows:count) 0)
|
||||
(star-glows:render)))))
|
||||
|
||||
(fn render [cam-x cam-y cam-z]
|
||||
(fn render [cam-x cam-y cam-z wireframe]
|
||||
(when (not sky-mesh) (create-sky-dome))
|
||||
(when sky-mesh
|
||||
(pxl8.draw_mesh sky-mesh {:x cam-x :y cam-y :z cam-z :passthrough true})))
|
||||
(pxl8.draw_mesh sky-mesh {:x cam-x :y cam-y :z cam-z :passthrough true :wireframe wireframe})))
|
||||
|
||||
{:render render
|
||||
:render-stars render-stars
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue