fix star projection

This commit is contained in:
asrael 2026-01-23 11:04:05 -06:00
parent c771fa665d
commit df5d905050
22 changed files with 612 additions and 660 deletions

View file

@ -496,7 +496,7 @@
(pxl8.end_frame_3d))
(sky.render-stars cam-yaw cam-pitch 1.0 last-dt)
(sky.render-stars smooth-cam-x eye-y smooth-cam-z 1.0 last-dt)
(let [cx (/ (pxl8.get_width) 2)
cy (/ (pxl8.get_height) 2)

View file

@ -40,20 +40,20 @@
(pxl8.gui_window 200 100 240 200 "pxl8 demo")
(when (gui:button 1 215 140 210 30 "Resume")
(when (gui:button 1 215 147 210 30 "Resume")
(hide))
(let [music-label (if (music.is-playing) "Music: On" "Music: Off")]
(when (gui:button 3 215 175 210 30 music-label)
(when (gui:button 3 215 182 210 30 music-label)
(if (music.is-playing)
(music.stop)
(music.start))))
(let [wire-label (if wireframe "Wireframe: On" "Wireframe: Off")]
(when (gui:button 4 215 210 210 30 wire-label)
(when (gui:button 4 215 217 210 30 wire-label)
(set wireframe (not wireframe))))
(when (gui:button 2 215 245 210 30 "Quit")
(when (gui:button 2 215 252 210 30 "Quit")
(pxl8.quit))
(if (gui:is_hovering)

View file

@ -1,4 +1,3 @@
(local ffi (require :ffi))
(local pxl8 (require :pxl8))
(local effects (require :pxl8.effects))
@ -21,10 +20,13 @@
;; Blue/magic: indices 176-178 (purples - brightest of the range)
(local IDX_MAGIC 176)
(var sky-mesh nil)
(var star-time 0)
(var last-gradient-key nil)
(var random-stars [])
(var sky-mesh nil)
(var star-count 0)
(var star-directions 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]
@ -161,99 +163,88 @@
(when (> dy -0.1)
(table.insert tiny-stars {:dx dx :dy dy :dz dz
:brightness brightness
:color color}))))))
:color color})))))
(fn project-direction [dir-x dir-y dir-z yaw pitch cos-rot sin-rot width height]
(let [rot-x (- (* dir-x cos-rot) (* dir-z sin-rot))
rot-z (+ (* dir-x sin-rot) (* dir-z cos-rot))
cos-yaw (math.cos yaw)
sin-yaw (math.sin yaw)
cos-pitch (math.cos pitch)
sin-pitch (math.sin pitch)
rotated-x (+ (* rot-x cos-yaw) (* rot-z sin-yaw))
rotated-z (+ (* (- rot-x) sin-yaw) (* rot-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))})))))
(set star-count (+ (length tiny-stars) (length random-stars)))
(set star-directions (pxl8.create_vec3_array star-count))
(set star-projected (pxl8.create_vec3_array star-count))
(fn render-stars [yaw pitch intensity dt]
(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 (> intensity 0)
(let [width (pxl8.get_width)
height (pxl8.get_height)
glows []
(when (and (> intensity 0) (> star-count 0))
(let [glows []
fade-in (* intensity intensity)
time-factor (/ star-time 60)
star-rotation (/ (* star-time math.pi 2) STAR_CYCLE_PERIOD)
cos-rot (math.cos star-rotation)
sin-rot (math.sin star-rotation)]
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)]
(each [i star (ipairs tiny-stars)]
(let [screen (project-direction star.dx star.dy star.dz yaw pitch cos-rot sin-rot width height)]
(when screen
(let [int (math.floor (* star.brightness fade-in))]
(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
(table.insert glows {:x (math.floor screen.x) :y (math.floor screen.y)
:radius 1
:intensity int
:color star.color
:shape effects.GLOW_CIRCLE}))))))
(each [i star (ipairs random-stars)]
(let [screen (project-direction star.dx star.dy star.dz yaw pitch cos-rot sin-rot width height)]
(when screen
(let [phase (+ (* i 2.137) (* time-factor 3.0))
(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))]
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 3
(table.insert glows {:x sx :y sy :radius 3
:intensity (math.floor (* int 1.5))
:color star.color
:shape effects.GLOW_DIAMOND})
(table.insert glows {:x screen.x :y screen.y
:radius 5
:color star.color :shape effects.GLOW_DIAMOND})
(table.insert glows {:x sx :y sy :radius 5
:intensity (math.floor (/ int 2))
:color star.color
:shape effects.GLOW_CIRCLE}))
:color star.color :shape effects.GLOW_CIRCLE}))
(> star.brightness 180)
(do
(table.insert glows {:x screen.x :y screen.y
:radius 2
:intensity int
:color star.color
:shape effects.GLOW_DIAMOND})
(table.insert glows {:x screen.x :y screen.y
:radius 4
(table.insert glows {:x sx :y sy :radius 2 :intensity int
:color star.color :shape effects.GLOW_DIAMOND})
(table.insert glows {:x sx :y sy :radius 4
:intensity (math.floor (/ int 3))
:color star.color
:shape effects.GLOW_CIRCLE}))
:color star.color :shape effects.GLOW_CIRCLE}))
(> star.brightness 120)
(do
(table.insert glows {:x screen.x :y screen.y
:radius 2
(table.insert glows {:x sx :y sy :radius 2
:intensity (math.floor (* int 0.67))
:color star.color
:shape effects.GLOW_DIAMOND})
(table.insert glows {:x screen.x :y screen.y
:radius 3
:color star.color :shape effects.GLOW_DIAMOND})
(table.insert glows {:x sx :y sy :radius 3
:intensity (math.floor (/ int 4))
:color star.color
:shape effects.GLOW_CIRCLE}))
(table.insert glows {:x screen.x :y screen.y
:radius 2
:color star.color :shape effects.GLOW_CIRCLE}))
(table.insert glows {:x sx :y sy :radius 2
:intensity (math.floor (* int 0.5))
:color star.color
:shape effects.GLOW_CIRCLE}))))))
:color star.color :shape effects.GLOW_CIRCLE}))))))
(when (> (length glows) 0)
(effects.glows glows)))))