improve sw renderer
This commit is contained in:
parent
415d424057
commit
39ee0fefb7
89 changed files with 9380 additions and 2307 deletions
|
|
@ -1,13 +1,18 @@
|
|||
(local pxl8 (require :pxl8))
|
||||
(local effects (require :pxl8.effects))
|
||||
(local net (require :pxl8.net))
|
||||
|
||||
(local colormap (require :mod.colormap))
|
||||
(local menu (require :mod.menu))
|
||||
(local palette (require :mod.palette))
|
||||
(local sky (require :mod.sky))
|
||||
(local textures (require :mod.textures))
|
||||
|
||||
(local bob-amount 4.0)
|
||||
(local bob-speed 8.0)
|
||||
(local cam-smoothing 0.25)
|
||||
(local cell-size 64)
|
||||
(local cursor-sensitivity 0.008)
|
||||
(local cursor-sensitivity 0.010)
|
||||
(local gravity -800)
|
||||
(local grid-size 64)
|
||||
(local ground-y 64)
|
||||
|
|
@ -16,7 +21,7 @@
|
|||
(local land-squash-amount -4)
|
||||
(local max-pitch 1.5)
|
||||
(local move-speed 200)
|
||||
(local turn-speed 2.0)
|
||||
(local turn-speed 4.0)
|
||||
|
||||
(local sim-tick-rate 60)
|
||||
(local sim-dt (/ 1.0 sim-tick-rate))
|
||||
|
|
@ -32,10 +37,10 @@
|
|||
(var cam-yaw 0)
|
||||
(var cam-z 1000)
|
||||
(var camera nil)
|
||||
(var cursor-look? true)
|
||||
(var grounded? true)
|
||||
(var land-squash 0)
|
||||
(var light-time 0)
|
||||
(var real-time 0)
|
||||
(var network nil)
|
||||
(var smooth-cam-x 1000)
|
||||
(var smooth-cam-z 1000)
|
||||
|
|
@ -43,16 +48,148 @@
|
|||
(var world nil)
|
||||
(var fps-avg 0)
|
||||
(var fps-sample-count 0)
|
||||
(var fireball-mesh nil)
|
||||
(var last-dt 0.016)
|
||||
(var lights nil)
|
||||
|
||||
(local FIREBALL_COLOR 184)
|
||||
(local cursor-look? true)
|
||||
(local FIREBALL_COLOR 218)
|
||||
(local STONE_FLOOR_START 37)
|
||||
(local STONE_WALL_START 2)
|
||||
(local MOSS_COLOR 200)
|
||||
|
||||
(fn init-fireball-palette []
|
||||
(for [i 0 7]
|
||||
(let [t (/ i 7)
|
||||
r (math.floor (+ 0xFF (* t 0)))
|
||||
g (math.floor (+ 0x60 (* t (- 0xE0 0x60))))
|
||||
b (math.floor (+ 0x10 (* t (- 0x80 0x10))))]
|
||||
(pxl8.set_palette_rgb (+ FIREBALL_COLOR i) r g b))))
|
||||
(local trail-positions [])
|
||||
(local TRAIL_LENGTH 8)
|
||||
|
||||
(fn create-fireball-mesh []
|
||||
(let [verts []
|
||||
indices []
|
||||
radius 5
|
||||
rings 4
|
||||
segments 6
|
||||
core-color (+ FIREBALL_COLOR 6)
|
||||
spike-color (+ FIREBALL_COLOR 2)]
|
||||
|
||||
;; top pole
|
||||
(table.insert verts {:x 0 :y radius :z 0 :nx 0 :ny 1 :nz 0 :color core-color :light 255})
|
||||
|
||||
;; sphere rings
|
||||
(for [ring 1 (- rings 1)]
|
||||
(let [phi (* (/ ring rings) math.pi)
|
||||
sin-phi (math.sin phi)
|
||||
cos-phi (math.cos phi)
|
||||
y (* radius cos-phi)
|
||||
ring-radius (* radius sin-phi)]
|
||||
(for [seg 0 (- segments 1)]
|
||||
(let [theta (* (/ seg segments) math.pi 2)
|
||||
x (* ring-radius (math.cos theta))
|
||||
z (* ring-radius (math.sin theta))
|
||||
nx (* sin-phi (math.cos theta))
|
||||
nz (* sin-phi (math.sin theta))]
|
||||
(table.insert verts {:x x :y y :z z :nx nx :ny cos-phi :nz nz :color core-color :light 255})))))
|
||||
|
||||
;; bottom pole
|
||||
(let [bottom-idx (length verts)]
|
||||
(table.insert verts {:x 0 :y (- radius) :z 0 :nx 0 :ny -1 :nz 0 :color core-color :light 255})
|
||||
|
||||
;; top cap triangles
|
||||
(for [seg 0 (- segments 1)]
|
||||
(let [next-seg (% (+ seg 1) segments)]
|
||||
(table.insert indices 0)
|
||||
(table.insert indices (+ 1 next-seg))
|
||||
(table.insert indices (+ 1 seg))))
|
||||
|
||||
;; middle quads
|
||||
(for [ring 0 (- rings 3)]
|
||||
(for [seg 0 (- segments 1)]
|
||||
(let [next-seg (% (+ seg 1) segments)
|
||||
curr-row (+ 1 (* ring segments))
|
||||
next-row (+ 1 (* (+ ring 1) segments))]
|
||||
(table.insert indices (+ curr-row seg))
|
||||
(table.insert indices (+ curr-row next-seg))
|
||||
(table.insert indices (+ next-row seg))
|
||||
(table.insert indices (+ curr-row next-seg))
|
||||
(table.insert indices (+ next-row next-seg))
|
||||
(table.insert indices (+ next-row seg)))))
|
||||
|
||||
;; bottom cap triangles
|
||||
(let [last-ring-start (+ 1 (* (- rings 2) segments))]
|
||||
(for [seg 0 (- segments 1)]
|
||||
(let [next-seg (% (+ seg 1) segments)]
|
||||
(table.insert indices bottom-idx)
|
||||
(table.insert indices (+ last-ring-start seg))
|
||||
(table.insert indices (+ last-ring-start next-seg))))))
|
||||
|
||||
;; add spikes - evenly distributed using golden ratio
|
||||
(let [num-spikes 12
|
||||
spike-len 8
|
||||
base-size 1.2
|
||||
golden-ratio (/ (+ 1 (math.sqrt 5)) 2)]
|
||||
(for [i 0 (- num-spikes 1)]
|
||||
(let [;; fibonacci sphere distribution
|
||||
y (- 1 (* (/ i (- num-spikes 1)) 2))
|
||||
r-at-y (math.sqrt (- 1 (* y y)))
|
||||
theta (* math.pi 2 i golden-ratio)
|
||||
nx (* r-at-y (math.cos theta))
|
||||
ny y
|
||||
nz (* r-at-y (math.sin theta))
|
||||
;; tangent vectors for base
|
||||
tx (if (> (math.abs ny) 0.9) 1 0)
|
||||
ty (if (> (math.abs ny) 0.9) 0 1)
|
||||
tz 0
|
||||
;; cross product for perpendicular
|
||||
px (- (* ty nz) (* tz ny))
|
||||
py (- (* tz nx) (* tx nz))
|
||||
pz (- (* tx ny) (* ty nx))
|
||||
pl (math.sqrt (+ (* px px) (* py py) (* pz pz)))
|
||||
px (/ px pl) py (/ py pl) pz (/ pz pl)
|
||||
;; second perpendicular
|
||||
qx (- (* ny pz) (* nz py))
|
||||
qy (- (* nz px) (* nx pz))
|
||||
qz (- (* nx py) (* ny px))
|
||||
;; base center inside sphere
|
||||
bx (* radius 0.8 nx)
|
||||
by (* radius 0.8 ny)
|
||||
bz (* radius 0.8 nz)
|
||||
;; spike tip
|
||||
sx (* (+ radius spike-len) nx)
|
||||
sy (* (+ radius spike-len) ny)
|
||||
sz (* (+ radius spike-len) nz)
|
||||
base-idx (length verts)]
|
||||
;; 4 base vertices forming a square
|
||||
(table.insert verts {:x (+ bx (* base-size px) (* base-size qx))
|
||||
:y (+ by (* base-size py) (* base-size qy))
|
||||
:z (+ bz (* base-size pz) (* base-size qz))
|
||||
:nx nx :ny ny :nz nz :color core-color :light 255})
|
||||
(table.insert verts {:x (+ bx (* base-size px) (* (- base-size) qx))
|
||||
:y (+ by (* base-size py) (* (- base-size) qy))
|
||||
:z (+ bz (* base-size pz) (* (- base-size) qz))
|
||||
:nx nx :ny ny :nz nz :color core-color :light 255})
|
||||
(table.insert verts {:x (+ bx (* (- base-size) px) (* (- base-size) qx))
|
||||
:y (+ by (* (- base-size) py) (* (- base-size) qy))
|
||||
:z (+ bz (* (- base-size) pz) (* (- base-size) qz))
|
||||
:nx nx :ny ny :nz nz :color core-color :light 255})
|
||||
(table.insert verts {:x (+ bx (* (- base-size) px) (* base-size qx))
|
||||
:y (+ by (* (- base-size) py) (* base-size qy))
|
||||
:z (+ bz (* (- base-size) pz) (* base-size qz))
|
||||
:nx nx :ny ny :nz nz :color core-color :light 255})
|
||||
;; spike tip
|
||||
(table.insert verts {:x sx :y sy :z sz :nx nx :ny ny :nz nz :color spike-color :light 255})
|
||||
;; 4 triangular faces of pyramid
|
||||
(table.insert indices base-idx)
|
||||
(table.insert indices (+ base-idx 1))
|
||||
(table.insert indices (+ base-idx 4))
|
||||
(table.insert indices (+ base-idx 1))
|
||||
(table.insert indices (+ base-idx 2))
|
||||
(table.insert indices (+ base-idx 4))
|
||||
(table.insert indices (+ base-idx 2))
|
||||
(table.insert indices (+ base-idx 3))
|
||||
(table.insert indices (+ base-idx 4))
|
||||
(table.insert indices (+ base-idx 3))
|
||||
(table.insert indices base-idx)
|
||||
(table.insert indices (+ base-idx 4)))))
|
||||
|
||||
(set fireball-mesh (pxl8.create_mesh verts indices))))
|
||||
|
||||
(var client-tick 0)
|
||||
(var last-processed-tick 0)
|
||||
|
|
@ -99,10 +236,22 @@
|
|||
|
||||
(values new-x new-z))
|
||||
(fn init []
|
||||
(pxl8.set_relative_mouse_mode true)
|
||||
(pxl8.set_palette palette 256)
|
||||
(pxl8.set_colormap colormap 16384)
|
||||
(for [i 0 7]
|
||||
(let [t (/ i 7)
|
||||
r 0xFF
|
||||
g (math.floor (+ 0x60 (* t (- 0xE0 0x60))))
|
||||
b (math.floor (+ 0x10 (* t (- 0x80 0x10))))]
|
||||
(pxl8.set_palette_rgb (+ FIREBALL_COLOR i) r g b)))
|
||||
(sky.update-gradient 1 2 6 6 10 18)
|
||||
(pxl8.update_palette_deps)
|
||||
(set camera (pxl8.create_camera_3d))
|
||||
(set world (pxl8.create_world))
|
||||
(set lights (pxl8.create_lights))
|
||||
(sky.generate-stars 12345)
|
||||
(init-fireball-palette)
|
||||
(create-fireball-mesh)
|
||||
|
||||
(set network (net.Net.new {:port 7777}))
|
||||
(when network
|
||||
|
|
@ -119,17 +268,9 @@
|
|||
:num_rooms 20})]
|
||||
(if (< result 0)
|
||||
(pxl8.error (.. "Failed to generate rooms - result: " result))
|
||||
(let [floor-tex (pxl8.procgen_tex {:name "floor"
|
||||
:seed 11111
|
||||
:width 64
|
||||
:height 64
|
||||
:base_color 19})
|
||||
wall-tex (pxl8.procgen_tex {:name "wall"
|
||||
:seed 12345
|
||||
:width 64
|
||||
:height 64
|
||||
:base_color 4})
|
||||
sky-tex (pxl8.create_texture [0] 1 1)]
|
||||
(let [floor-tex (textures.mossy-cobblestone 44444 STONE_FLOOR_START MOSS_COLOR)
|
||||
wall-tex (textures.ashlar-wall 55555 STONE_WALL_START MOSS_COLOR)
|
||||
sky-tex (pxl8.create_texture [0] 1 1)]
|
||||
|
||||
(let [result (world:apply_textures [
|
||||
{:name "floor"
|
||||
|
|
@ -193,6 +334,7 @@
|
|||
(store-position t cam-x cam-z hist.yaw))))))))))
|
||||
|
||||
(fn update [dt]
|
||||
(set last-dt dt)
|
||||
(let [fps (pxl8.get_fps)]
|
||||
(set fps-sample-count (+ fps-sample-count 1))
|
||||
(set fps-avg (+ (* fps-avg (/ (- fps-sample-count 1) fps-sample-count))
|
||||
|
|
@ -234,9 +376,9 @@
|
|||
(when (and (not cursor-look?) (pxl8.key_down "down"))
|
||||
(set cam-pitch (math.max (- max-pitch) (- cam-pitch (* turn-speed dt)))))
|
||||
(when (and (not cursor-look?) (pxl8.key_down "left"))
|
||||
(set cam-yaw (+ cam-yaw (* turn-speed dt))))
|
||||
(when (and (not cursor-look?) (pxl8.key_down "right"))
|
||||
(set cam-yaw (- cam-yaw (* turn-speed dt))))
|
||||
(when (and (not cursor-look?) (pxl8.key_down "right"))
|
||||
(set cam-yaw (+ cam-yaw (* turn-speed dt))))
|
||||
|
||||
(when network
|
||||
(let [(ok err) (pcall (fn []
|
||||
|
|
@ -287,7 +429,8 @@
|
|||
(let [target-phase (* (math.floor (/ bob-time math.pi)) math.pi)]
|
||||
(set bob-time (+ (* bob-time 0.8) (* target-phase 0.2))))))
|
||||
|
||||
(set light-time (+ light-time (* dt 0.15))))))
|
||||
(set light-time (+ light-time (* dt 0.5)))
|
||||
(set real-time (+ real-time dt)))))
|
||||
|
||||
(fn frame []
|
||||
(pxl8.clear 1)
|
||||
|
|
@ -316,77 +459,57 @@
|
|||
[0 1 0])
|
||||
(camera:set_perspective 1.047 aspect 1.0 4096.0)
|
||||
|
||||
(let [light-pulse (+ 0.7 (* 0.3 (math.sin (* light-time 2))))
|
||||
forward-x (- (math.sin cam-yaw))
|
||||
forward-z (- (math.cos cam-yaw))
|
||||
light-x (+ smooth-cam-x (* 150 forward-x) (* 50 (math.cos light-time)))
|
||||
light-z (+ smooth-cam-z (* 150 forward-z) (* 50 (math.sin light-time)))
|
||||
light-y (+ eye-y 30)]
|
||||
(pxl8.begin_frame_3d camera {
|
||||
:ambient 80
|
||||
(let [light-x (+ 1000 (* 50 (math.cos light-time)))
|
||||
light-z (+ 940 (* 50 (math.sin light-time)))
|
||||
light-y 80
|
||||
phase (+ (* light-x 0.01) 1.7)
|
||||
f1 (* 0.08 (math.sin (+ (* real-time 2.5) phase)))
|
||||
f2 (* 0.05 (math.sin (+ (* real-time 4.1) (* phase 0.7))))
|
||||
f3 (* 0.03 (math.sin (+ (* real-time 7.3) (* phase 1.2))))
|
||||
flicker (+ 0.92 f1 f2 f3)
|
||||
light-intensity (math.floor (math.max 0 (math.min 255 (* 255 flicker))))
|
||||
r1 (* 0.06 (math.sin (+ (* real-time 1.8) (* phase 0.5))))
|
||||
r2 (* 0.04 (math.sin (+ (* real-time 3.2) phase)))
|
||||
light-radius (* 150 (+ 0.95 r1 r2))]
|
||||
(lights:clear)
|
||||
(lights:add light-x light-y light-z 255 200 150 light-intensity light-radius)
|
||||
(pxl8.begin_frame_3d camera lights {
|
||||
:ambient 30
|
||||
:fog_density 0.0
|
||||
:celestial_dir [0.5 -0.8 0.3]
|
||||
:celestial_intensity 0.5
|
||||
:lights [{:x light-x :y light-y :z light-z
|
||||
:r 255 :g 200 :b 150
|
||||
:intensity (* 255 light-pulse)
|
||||
:radius 400}]})
|
||||
:celestial_intensity 0.5})
|
||||
(pxl8.clear_depth)
|
||||
|
||||
(sky.update-gradient 1 2 6 6 10 18)
|
||||
(sky.render smooth-cam-x eye-y smooth-cam-z)
|
||||
(sky.render smooth-cam-x eye-y smooth-cam-z (menu.is-wireframe))
|
||||
(pxl8.clear_depth)
|
||||
|
||||
(world:set_wireframe (menu.is-wireframe) 15)
|
||||
(world:render [smooth-cam-x eye-y smooth-cam-z])
|
||||
|
||||
(pxl8.end_frame_3d)
|
||||
(when fireball-mesh
|
||||
(let [wire (menu.is-wireframe)]
|
||||
(pxl8.draw_mesh fireball-mesh {:x light-x :y light-y :z light-z
|
||||
:passthrough true
|
||||
:wireframe wire
|
||||
:emissive 1.0})))
|
||||
|
||||
(let [dx (- light-x smooth-cam-x)
|
||||
dy (- light-y eye-y)
|
||||
dz (- light-z smooth-cam-z)
|
||||
dist (math.sqrt (+ (* dx dx) (* dy dy) (* dz dz)))]
|
||||
(when (> dist 1)
|
||||
(let [inv-dist (/ 1 dist)
|
||||
dir-x (* dx inv-dist)
|
||||
dir-y (* dy inv-dist)
|
||||
dir-z (* dz inv-dist)
|
||||
cos-yaw (math.cos cam-yaw)
|
||||
sin-yaw (math.sin cam-yaw)
|
||||
cos-pitch (math.cos cam-pitch)
|
||||
sin-pitch (math.sin cam-pitch)
|
||||
rx (+ (* dir-x cos-yaw) (* dir-z sin-yaw))
|
||||
rz (+ (* (- dir-x) sin-yaw) (* dir-z cos-yaw))
|
||||
ry (- (* dir-y cos-pitch) (* rz sin-pitch))
|
||||
fz (+ (* dir-y sin-pitch) (* rz cos-pitch))]
|
||||
(when (> fz 0.01)
|
||||
(let [width (pxl8.get_width)
|
||||
height (pxl8.get_height)
|
||||
fov 1.047
|
||||
half-fov-tan (math.tan (* fov 0.5))
|
||||
ndc-x (/ rx (* fz half-fov-tan aspect))
|
||||
ndc-y (/ ry (* fz half-fov-tan))
|
||||
sx (math.floor (* (+ 1 ndc-x) 0.5 width))
|
||||
sy (math.floor (* (- 1 ndc-y) 0.5 height))
|
||||
screen-size (/ 400 dist)
|
||||
base-radius (math.max 2 (math.min 12 (math.floor screen-size)))
|
||||
pulse-int (math.floor (* 180 light-pulse))]
|
||||
(when (and (>= sx 0) (< sx width) (>= sy 0) (< sy height))
|
||||
(effects.glows [
|
||||
{:x sx :y sy :radius (+ base-radius 2) :intensity (/ pulse-int 5) :color (+ FIREBALL_COLOR 1) :shape effects.GLOW_CIRCLE}
|
||||
{:x sx :y sy :radius base-radius :intensity pulse-int :color (+ FIREBALL_COLOR 5) :shape effects.GLOW_DIAMOND}]))))))))
|
||||
(pxl8.end_frame_3d))
|
||||
|
||||
(sky.render-stars cam-yaw cam-pitch 1.0)
|
||||
(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)
|
||||
crosshair-size 4
|
||||
red-color 18]
|
||||
(pxl8.line (- cx crosshair-size) cy (+ cx crosshair-size) cy red-color)
|
||||
(pxl8.line cx (- cy crosshair-size) cx (+ cy crosshair-size) red-color))
|
||||
crosshair-color 240
|
||||
text-color 251]
|
||||
(pxl8.line (- cx crosshair-size) cy (+ cx crosshair-size) cy crosshair-color)
|
||||
(pxl8.line cx (- cy crosshair-size) cx (+ cy crosshair-size) crosshair-color)
|
||||
|
||||
(pxl8.text (.. "fps: " (string.format "%.0f" fps-avg)) 5 5 12)
|
||||
(pxl8.text (.. "pos: " (string.format "%.0f" cam-x) ","
|
||||
(string.format "%.0f" cam-y) ","
|
||||
(string.format "%.0f" cam-z)) 5 15 12))))
|
||||
(pxl8.text (.. "fps: " (string.format "%.0f" fps-avg)) 5 5 text-color)
|
||||
(pxl8.text (.. "pos: " (string.format "%.0f" cam-x) ","
|
||||
(string.format "%.0f" cam-y) ","
|
||||
(string.format "%.0f" cam-z)) 5 15 text-color)))))
|
||||
|
||||
{:init init
|
||||
:update update
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue