luv

Workshop wiki

render.lisp

luft/render/render.lisp

system luft/renderer · 116 definitions · on GitHub

in-package#:luft.render
defparameter*wireframe*0.0"Global construction-edge strength. The atelier toggles it between 0 and 1."
defparameter*render-scale*0.75"Linear internal resolution of the LUFT scene before temporal upscaling."
defparameter*temporal-upscaling-p*t"Whether LUFT uses MetalFX temporal reconstruction on Metal devices."
defparameter*sanctuary-beacon-x*58
defparameter*sanctuary-beacon-y*54
defclassscene
solid:initarg:solid:readerscene-solid
material-vocabulary:initarg:material-vocabulary:readerscene-material-vocabulary
material-cells:initarg:material-cells:readerscene-material-cells
material-program:initarg:material-program:readerscene-material-program
player-p:initarg:player-p:initformnil:readerscene-player-p
:documentation

One authored solid and its vocabulary-closed material-placement field.

The solid remains luft's topological truth. The sparse authored field stores only dense vocabulary offsets; semantic material objects remain at the scene boundary rather than being allocated per cell.

defclassscene-builder
domain:initarg:domain:readerscene-builder-domain
origin-x:initarg:origin-x:initform0:readerscene-builder-origin-x
origin-y:initarg:origin-y:initform0:readerscene-builder-origin-y
cells:initform
make-hash-table:test#'eql
:readerscene-builder-cells
material-vocabulary:initform:readerscene-builder-material-vocabulary
material-cells:initform
make-hash-table:test#'eql
:readerscene-builder-material-cells
defunmake-scene-builder
&key
horizontal-bits6
origin-x0
origin-y0
make-instance'scene-builder:domain
luft:make-world-domain:x-bitshorizontal-bits:y-bitshorizontal-bits
:origin-xorigin-x:origin-yorigin-y
defunscene-builder-cell
builderxyz&key
solid-pt
architecture-p
materialnilmaterial-p
when
<=0z254
let
site
luft:make-site
scene-builder-domainbuilder
+x
scene-builder-origin-xbuilder
+y
scene-builder-origin-ybuilder
zluft:+cell-extent+1
ifsolid-p
let
placement
check-typeplacementmaterial-placement
setf
gethashsite
scene-builder-cellsbuilder
t
gethashsite
scene-builder-material-cellsbuilder
domains:identity-vocabulary-offset
scene-builder-material-vocabularybuilder
placement
progn
remhashsite
scene-builder-cellsbuilder
remhashsite
scene-builder-material-cellsbuilder
builder
defunscene-builder-box
builderx0x1y0y1z0z1&key
solid-pt
architecture-p
loopforzfromz0toz1do
loopforyfromy0toy1do
loopforxfromx0tox1do
scene-builder-cellbuilderxyz:solid-psolid-p:materialmaterial
builder
defunscene-builder-disc
buildercxcyradiusz0z1&key
solid-pt
architecture-p
let
limit
expt
+radius0.5
2
loopforxfrom
-cx
ceilingradius
to
+cx
ceilingradius
do
loopforyfrom
-cy
ceilingradius
to
+cy
ceilingradius
fordx=
-
+x0.5
+cx0.5
fordy=
-
+y0.5
+cy0.5
when
<=
+
*dxdx
*dydy
limit
do
loopforzfromz0toz1do
scene-builder-cellbuilderxyz:solid-psolid-p:materialmaterial
builder
defunscene-builder-ring
buildercxcyinnerouterz0z1&key
solid-pt
architecture-p
let
low
expt
+inner0.5
2
high
expt
+outer0.5
2
loopforxfrom
-cx
ceilingouter
to
+cx
ceilingouter
do
loopforyfrom
-cy
ceilingouter
to
+cy
ceilingouter
fordx=
-
+x0.5
+cx0.5
fordy=
-
+y0.5
+cy0.5
fordistance=
+
*dxdx
*dydy
whendo
loopforzfromz0toz1do
scene-builder-cellbuilderxyz:solid-psolid-p:materialmaterial
builder
defunarch-rise
offsetradius
let
square
-
*radiusradius
*offsetoffset
if
pluspsquare
round
sqrtsquare
0
defunscene-builder-carve-arch
buildercentrefloorspringingradiusacross&key
destructuring-bind
near.far
across
loopforoffsetfrom
-radius
toradiusforrise=
arch-riseoffsetradius
when
plusprise
do
loopforzfromfloorbelow
+springingrise
do
loopforotherfromneartofardo
if
eqaxis:x
scene-builder-cellbuilder
+centreoffset
otherz:solid-pnil
scene-builder-cellbuilderother
+centreoffset
z:solid-pnil
builder
defunscene-builder-corbel
builderx0x1y0y1zcourses
loopforcoursefrom0belowcoursesforout=
1+course
do
scene-builder-boxbuilder
-x0out
+x1out
-y0out
+y1out
+zcourse
+zcourse
:architecture-pt
builder
defunscene-builder-crenellate
builderx0x1y0y1z
loopforxfromx0tox1do
loopforyfromy0toy1when
and
or
=xx0
=xx1
=yy0
=yy1
zerop
mod
+xy
2
do
scene-builder-cellbuilderxyz:architecture-pt
scene-builder-cellbuilderxy
1+z
:architecture-pt
builder
defunscene-builder-staircase
builderx0x1y0step-countbase-top&key
boundary:open

Author an ascending masonry stair and its optional support boundary.

boundary is a deliberately small modeling vocabulary. :OPEN emits only the treads, :BORDER adds a one-cell stone strip level with each tread, and :LOW-WALL raises that strip one course above it. The extra cells are ordinary authored solid and material input; the bevel mesher receives no special-case stair topology. #WSEK3C

check-typeboundary
member:open:border:low-wall
let
boundary-rise
ecaseboundary
:opennil
:border0
:low-wall1
loopforstepbelowstep-countforyfromy0fortop=
+base-topstep
do
scene-builder-boxbuilderx0x1yy0top:architecture-pt
whenboundary-rise
scene-builder-boxbuilder
1-x0
1-x0
yy0
+topboundary-rise
:architecture-pt
scene-builder-boxbuilder
1+x1
1+x1
yy0
+topboundary-rise
:architecture-pt
builder
defunfinish-scene-builder
builder&keyplayer-p
let*
cells
scene-builder-cellsbuilder
chain-builder
luft:make-chain-builder
scene-builder-domainbuilder
:initial-capacity
hash-table-countcells
maphash
lambda
sitepresent-p
declare
ignorepresent-p
cells
make-instance'scene:solid:player-pplayer-p:material-vocabulary
scene-builder-material-vocabularybuilder
:material-program
make-material-program
scene-builder-material-vocabularybuilder
:material-cells
scene-builder-material-cellsbuilder
defunmake-manifold-spike-scene

Three isolated singular-star fixtures for the manifold-sheet spike.

The plots exercise an edge-touching pair, a corner-touching pair, and the four-sheet parity star. Nothing else in the scene can hide their junctions. #WSEK3C

let
builder
make-scene-builder:horizontal-bits6
labels
place-star
maskcentre-x
dotimes
when
logbitpsamplemask
scene-builder-cellbuilder
+centre-x
if
logbitp0sample
0-1
+10
if
logbitp1sample
0-1
+6
if
logbitp2sample
0-1
place-star#x0610
place-star#x1814
place-star#x6918
defunmake-bevel-limit-study-scene

One isolated stone cell for comparing sub-medial and medial bevels.

let
builder
make-scene-builder:horizontal-bits4
scene-builder-cellbuilder643:architecture-pt
defunmountain-sanctuary-terrain-height
xy

The authored local-coordinate height of the sanctuary's mountain world.

let
shore11
water2
floor
cond
<y14
maxwater
+shore
*1.4
sin
/x11.0
*1.1
sin
/
+x
*0.75y
9.0
-
*1.6
max0
-y9

A long diagonal shoulder lifts the far eastern approach without changing the bridge landing.

*0.10
max0
-
-x
*0.9y
58
>=y36
let*
edge
+2.0
*3.0
sin
/x9.0
*1.5
sin
/x3.7
inland
-y36edge
if
>=inland0
let*
ridge
min11.0
*0.22
max0
-
+y
*0.55x
88
ravine
max0.0
-4.5
*1.35
abs
-y
+67
*0.34x
rolling
*1.3
sin
/x12.0
cos
/y13.0
+plateaurollingridge
-ravine
maxwater
+plateau
*9.0inland
twater
defunmountain-sanctuary-terrain-x-bounds
y

Return the authored inclusive terrain span at local Y.

when
<=-15y81
values
max-18
+-17
round
*1.8
sin
/y6.0
min82
-81
round
*2.2
cos
/y8.0
t
defunscene-builder-mountain-border-wall
builder

Guard the elevated authored rim with a limestone parapet.

The continuous two-course body exceeds the player's one-cell step. Every other column rises into a third course, making the finite scenery legible as an intentional battlement rather than the accidental edge of a voxel field.

labels
wall-column
xy

The side contours follow the terrain's authored west/east banks.

loopforyfrom-15to81do
multiple-value-bind
westeastpresent-p
whenpresent-p
wall-columnwesty
wall-columneasty

Close the elevated northern rim between those side contours.

multiple-value-bind
westeastpresent-p
whenpresent-p
loopforxfromwesttoeastdo
wall-columnx81
builder
defunmake-mountain-sanctuary-scene
&key
stair-boundary:low-wall

A broad Lonely-Mountains world carrying a bridge and walled sanctuary.

This is the old Holm's architectural sentence with its material menagerie removed: rolling approaches, a channel and rising high rock; a diagonal processional way; a two-arched stone bridge; a gate, curtain wall, paired turrets, an arcaded hall and a remote ridge beacon.

let*
builder
water2
deck13
springing7
radius4
across
cons2732

Keep the packed world bounded away from its toroidal seam, while the visible camera sees terrain continuing beyond every frame edge.

loopforyfrom-15to81do
multiple-value-bind
westeastpresent-p
whenpresent-p
loopforxfromwesttoeastdo

A diagonal, gently climbing processional way makes the bridge belong to the low country instead of beginning at the edge of the model.

loopforstepfrom0below20forx=fory=fortop=do
scene-builder-boxbuilderx
+x4
y
1+y
0top:architecture-pt
when
zerop
scene-builder-cellbuilderxy
1+top
:architecture-pt
scene-builder-cellbuilder
+x4
1+y
1+top
:architecture-pt
dolist
y'
152535
scene-builder-boxbuilder2633
1-y
1+y
waterspringing:architecture-pt
scene-builder-boxbuilder27321238water
1-deck
:architecture-pt
dolist
arch'
2030
scene-builder-carve-archbuilderarch
1+water
springingradiusacross:axis:y
scene-builder-corbelbuilder2732842
1-deck
1
scene-builder-boxbuilder2534644deckdeck:architecture-pt
check-typestair-boundary
member:open:border:low-wall

The old bridge rail overlaps the first six stair courses. Preserve it for the open historical scene, but let authored stair boundaries own that stretch so the comparison changes one modeling decision at a time.

loopforyfrom6to
if
eqstair-boundary:open
4438
do
scene-builder-cellbuilder25y
1+deck
:architecture-pt
scene-builder-cellbuilder34y
1+deck
:architecture-pt
when
zerop
mody5
scene-builder-cellbuilder25y
+deck2
:architecture-pt
scene-builder-cellbuilder34y
+deck2
:architecture-pt
scene-builder-boxbuilder26333847deck
+plateau5
:solid-pnil
scene-builder-staircasebuilder2633397deck:boundarystair-boundary

Bed the sanctuary into the uneven ridge before raising its walls. The two-course podium is shallow enough to disappear into the higher turf, but where the mountain falls away it remains a continuous load path instead of leaving the fixed-height curtain visibly suspended in air. Its wider tower shoes also give the round keeps a deliberate transition into the rectilinear retaining work.

scene-builder-boxbuilder13474448
-plateau2
1-plateau
:architecture-pt
scene-builder-boxbuilder13174962
-plateau2
1-plateau
:architecture-pt
scene-builder-boxbuilder43474962
-plateau2
1-plateau
:architecture-pt
scene-builder-boxbuilder18425962
-plateau2
1-plateau
:architecture-pt
dolist
corner'
1546
4546
destructuring-bind
cxcy
corner
scene-builder-discbuildercxcy6
-plateau2
1-plateau
:architecture-pt
scene-builder-boxbuilder14464547plateau
+plateau6
:architecture-pt
scene-builder-boxbuilder14164561plateau
+plateau6
:architecture-pt
scene-builder-boxbuilder44464561plateau
+plateau6
:architecture-pt
scene-builder-corbelbuilder14464561
+plateau7
1
scene-builder-crenellatebuilder13474462
+plateau8
scene-builder-carve-archbuilder30plateau
+plateau3
3
cons4547
dolist
corner'
1546
4546
destructuring-bind
cxcy
corner
scene-builder-discbuildercxcy5
1-plateau
plateau:architecture-pt
scene-builder-ringbuildercxcy24plateau
+plateau9
:architecture-pt
scene-builder-ringbuildercxcy25
+plateau10
+plateau11
:architecture-pt
scene-builder-discbuildercxcy3
+plateau11
+plateau11
:architecture-pt
scene-builder-boxbuilder20405560plateau
+plateau5
:architecture-pt
scene-builder-boxbuilder21395659
1+plateau
+plateau5
:solid-pnil
dolist
bay'
253035
scene-builder-carve-archbuilderbay
1+plateau
+plateau3
2
cons5555

A hollow beacon on the eastern ridge gives the enlarged world a distant inhabited landmark and a second architectural scale.

let*
scene-builder-discbuilderbeacon-xbeacon-y3base
1+base
:materialbeacon-placement
scene-builder-ringbuilderbeacon-xbeacon-y12
+base2
+base6
:materialbeacon-placement
scene-builder-ringbuilderbeacon-xbeacon-y13
+base7
+base8
:materialbeacon-placement
scene-builder-discbuilderbeacon-xbeacon-y1
+base8
+base8
:materialbeacon-placement

An old eight-pillar sun court occupies the open lowland beside the processional way. Its diagonal stones echo the landscape's oblique ridges without competing with the sanctuary's larger silhouette.

let*
court-x55
court-y4
scene-builder-discbuildercourt-xcourt-y5basebase:architecture-pt
dolist
offset'
-40
-3-3
0-4
3-3
40
33
04
-33
destructuring-bind
dxdy
offset
scene-builder-boxbuilder
+court-xdx
+court-xdx
+court-ydy
+court-ydy
1+base
+base4
:architecture-pt
scene-builder-cellbuilder
+court-xdx
+court-ydy
+base5
:architecture-pt
finish-scene-builderbuilder:player-pt
defunmake-traveler-study-scene

A bare limestone dais under the traveler, clear from every direction.

The sanctuary is the scene he belongs in, but it is also a scene in which half the useful camera angles look through a parapet. This fixture keeps his exact world position and his exact deck height and removes everything else, so a turnaround can be shot around him without moving him.

let
builder
make-scene-builder:horizontal-bits7
scene-builder-boxbuilder566740581113:architecture-pt
finish-scene-builderbuilder:player-pt
defunmake-material-bevel-transition-study-scene

Build the five-cell medial T-junction regression. #WSEK3C

Two ascending architectural columns meet the corner of a two-cell terrain column. Widths one, two, and four occur in one tiny surface; the width-four medial collapse leaves exactly one long-edge/short-edge T-junction for the site-local contraction pass to resolve.

let
builder
make-scene-builder:horizontal-bits4
scene-builder-boxbuilder664423
scene-builder-cellbuilder542:architecture-pt
scene-builder-boxbuilder555523:architecture-pt
defunmake-miter-study-scene

Build the wall-side stepped mountain used to judge mixed miters. #Z5NDTA

The two L-shaped terraces retain five-, six-, and seven-cell vertex stars in one architectural context. Their back edges meet a continuous wall so the same view also retains the truncated wall miter preserved by #DJK8HW.

let
builder
make-scene-builder:horizontal-bits5

Broad plinth and continuous back wall.

scene-builder-boxbuilder2142801:architecture-pt
scene-builder-boxbuilder2148907:architecture-pt

One isolated terrain cell makes the ordinary boulder-on-ground contact inspectable beside the architectural mixed-miter cases.

The lower L supplies the outie, straight six-cell run, innie, and the first wall termination. The upper L repeats them without isolation.

scene-builder-boxbuilder4115722:architecture-pt
scene-builder-boxbuilder483422:architecture-pt
scene-builder-boxbuilder5106733:architecture-pt
scene-builder-boxbuilder574533:architecture-pt
defunface-solid-cell
solidface

Return the occupied cell incident to boundary face and which side it is on.

let*
back-x
if
eqaxis:x
1-x
x
back-y
if
eqaxis:y
1-y
y
back-z
if
eqaxis:z
1-z
z
if
valuesaxis:forward
values
luft:make-sitedomainback-xback-yback-zluft:+cell-extent+1
axis:backward
defunscene-foundation-cell-p

Whether architectural cell is immediately borne by non-architectural earth.

let
when
pluspz
let
and
multiple-value-bind
offsetpresent-p
gethashbelow
scene-material-cellsscene
andpresent-p
logtest+material-placement-earth-flag+
aref
material-program-placement-flags
scene-material-programscene
offset
defunscene-material-placement-at

Return the authored placement at occupied cell in scene.

multiple-value-bind
offsetpresent-p
gethashcell
scene-material-cellsscene
unlesspresent-p
error"Occupied scene cell ~S has no authored material placement."cell
domains:identity-vocabulary-member
scene-material-vocabularyscene
offset
defunscene-face-reading
sceneface

Derive face's semantic reading without allocating a per-face object.

multiple-value-bind
face-solid-cell
scene-solidscene
face
let
material-face-reading
material-placement-kindplacement
placementscenecellaxisside
defunmake-scene-face-stock-function

Capture scene's dense material tables for repeated face classification.

let*
solid
scene-solidscene
material-cells
scene-material-cellsscene
program
scene-material-programscene
placement-flags
the
simple-array
unsigned-byte8
material-program-placement-flagsprogram
face-stocks
the
simple-array
unsigned-byte16
material-program-placement-face-stocksprogram
labels
foundation-p
let
when
pluspz
let
and
multiple-value-bind
offsetpresent-p
gethashbelowmaterial-cells
andpresent-p
logtest+material-placement-earth-flag+
arefplacement-flagsoffset
lambda
face
declare
optimize
speed3
safety1
multiple-value-bind
multiple-value-bind
placement-offsetpresent-p
gethashcellmaterial-cells
unlesspresent-p
error"Occupied scene cell ~S has no authored material placement."cell
let*
flags
arefplacement-flagsplacement-offset
face-index
if6
+
*
ecaseaxis
:x0
:y1
:z2
2
if
eqside:forward
10
arefface-stocks
+face-index
defunscene-face-stock
sceneface

The current packed assembly offset for face in scene.

defunscene-chamfer-stock
stocks&optionalmaterial-program

Resolve one whole chamfer from its incident face stocks.

The paper palette's terrain top is grass, terrain side is soil, and terrain underside is dark soil. A unanimous closure continues that face material; a mixed terrain chamfer exposes soil. Stone--terrain chamfers retain the deepest incident substrate, so the shader can weather a turf line differently from an exposed or buried foundation without adding per-site material objects.

defunmake-render-mesh
source&keystock-functionchamfer-stock-function

Classify source into the face, edge, and vertex template-instance ABI.

let*
scene
and
typepsource'scene
source
solid
ifscene
scene-solidsource
source
material-program
andscene
scene-material-programscene
chamfer-stock-function
orchamfer-stock-function
check-typesolidluft:chain
zone
:luft/rematerialize:value
luft:make-surface-meshsolid:stock-functionstock-function:chamfer-stock-functionchamfer-stock-function:bevel-widthbevel-width
defunmake-material-bevel-mesh
sceneprofile&key
contract-t-junctions-pt

Build one watertight mesh with a semantic material width at each site.

The ordinary width-one mesher supplies one exact topology witness. profile is compiled after that build into a dense stock-to-material-mask lane. Each canonical lattice vertex ORs the masks of all incident stocks: terrain-only, architecture-only, and mixed stars select the profile's terrain, architecture, and contact widths. The unchanged witness triangles form the transitions.

The second value is a five-entry vector counting sites at widths zero through four; it is diagnostic evidence and does not become retained mesh state.

contract-t-junctions-p should remain true in production. NIL returns the deliberately open pre-contraction diagnostic mesh used to exhibit the exact medial T-junction repaired by the default path.

check-typescenescene
check-typeprofilematerial-bevel-profile

The witness build also interns every authored material assembly reached by the chamfer stock function. Freeze the dense policy only afterward.

let
witness
multiple-value-bind
stock-maskssite-widths
luft:vary-surface-mesh-bevel-widthswitness
lambda
xyzstocks
declare
ignorexyz
let
site-mask0
dolist
stockstocks
unless
<stock
lengthstock-masks
error"Mesh stock ~D is outside the compiled material bevel policy of ~D entries."stock
lengthstock-masks
setfsite-mask
logiorsite-mask
arefstock-masksstock
unless
<=1site-mask3
error"Incident mesh stocks ~S compiled to invalid material bevel mask ~D."stockssite-mask
arefsite-widthssite-mask
:contract-t-junctions-pcontract-t-junctions-p
defunmake-material-bevel-meshes
sceneprofile

Return the single site-local material bevel mesh in renderer slot zero.

defparameter*gallery*

Each entry is one isolated complex, named by the star configuration it is there to exhibit. Cells are offsets from the entry's plot origin.

'
:one-cell
000
:face-pair
000
100
:edge-pair
000
110
:corner-pair
000
111
:l-tromino
000
100
010
:square
000
100
010
110
:stair
000
100
101
:concave-vertex
000
100
010
110
001
101
011
:six-of-eight
000
100
010
110
001
101
:full-block
000
100
010
110
001
101
011
111
:tower
000
001
002
:cross
110
010
210
100
120
111
"Small unconnected complexes, one per interesting occupancy star."
defparameter*gallery-columns*4
defparameter*gallery-pitch*6
defungallery-plot-origin
index

Return the lattice origin of gallery entry index, laid out on a grid.

multiple-value-bind
rowcolumn
defunmake-gallery-solid
&key
entries*gallery*

Build one chain holding every gallery complex on its own plot.

Nothing here touches anything else, so each patch shown is entirely the consequence of its own occupancy star and can be read on its own.

let*
domain
luft:make-world-domain:x-bits6:y-bits6
builder
luft:make-chain-builderdomain:initial-capacity128
seen
make-hash-table:test#'eql
loopforentryinentriesforindexfrom0do
multiple-value-bind
oxoyoz
loopfor
dxdydz
in
secondentry
forsite=unless
gethashsiteseen
do
setf
gethashsiteseen
t
defungallery-plot-report
&key
entries*gallery*

Print where each gallery complex sits, so a capture can be aimed at one.

loopforentryinentriesforindexfrom0do
multiple-value-bind
xyz
formatt"~&~2D ~24A origin ~D,~D,~D~%"index
firstentry
xyz
values
defunmake-demo-solid

Make a compact stair-and-bridge solid with convex and concave stars.

let*
domain
luft:make-world-domain:x-bits5:y-bits5
builder
luft:make-chain-builderdomain:initial-capacity96
seen
make-hash-table:test#'eql
labels
cell
xyz
let
unless
gethashsiteseen
setf
gethashsiteseen
t
box
x0x1y0y1z0z1
loopforzfromz0toz1do
loopforyfromy0toy1do
loopforxfromx0tox1do
cellxyz
box41141111
box51051022
box666635
box996635
box669935
box999935
box696655
box699955
box787833
defstruct
render-population
:constructor%make-render-population
template-wordsinstance-wordstriangle-instance-countquad-instance-count
:copiernil

One compact fixed-arity draw population for a surface-mesh cohort.

template-words
:type
simple-array
unsigned-byte32
:read-onlyt
instance-words
:type
simple-array
unsigned-byte32
:read-onlyt
triangle-instance-count0:type
integer0*
:read-onlyt
quad-instance-count0:type
integer0*
:read-onlyt
defstruct
resident-population
:constructor%make-resident-population
populationinstance-buffertemplate-bufferbind-groupshadow-bind-group
:copiernil

One chunk's CPU population and independently retained GPU realization.

populationnil:typerender-population:read-onlyt
instance-buffernil:read-onlyt
template-buffernil:read-onlyt
bind-groupnil:read-onlyt
shadow-bind-groupnil:read-onlyt
defstruct
prepared-render-mesh
:constructor%make-prepared-render-mesh
meshpopulation
:copiernil

Worker-transferable CPU realization of one semantic surface mesh.

meshnil:typeluft:surface-mesh:read-onlyt
populationnil:typerender-population:read-onlyt
zdefun
prepare-render-mesh:zone:luft/prepare-population
mesh
"Canonicalize one MESH before it crosses to the renderer owner."
check-typemeshluft:surface-mesh
%make-prepared-render-meshmesh
defunmake-render-population
meshes

Canonicalize and concatenate meshes into two fixed-arity instance runs.

Every source template contains either one triangle or one quad. Templates are interned by their exact packed vertices, padded to a fixed six-vertex stride, and selected by the low sixteen bits of each remapped instance record. The returned population stores triangle instances first and quad instances second, so the complete surface needs at most two direct instanced draws.

let
template-index
make-hash-table:test#'equalp
template-words
make-array256:element-type'
unsigned-byte32
:adjustablet:fill-pointer0
triangle-words
make-array256:element-type'
unsigned-byte32
:adjustablet:fill-pointer0
quad-words
make-array256:element-type'
unsigned-byte32
:adjustablet:fill-pointer0
assembly-count
length
domains:identity-vocabulary-members*surface-assembly-vocabulary*
triangle-count0
quad-count0
labels
intern-template
meshtemplate-id
let*
ranges
luft:surface-mesh-template-rangesmesh
vertices
luft:surface-mesh-template-vertex-wordsmesh
range-offset
*2template-id
vertex-start
arefrangesrange-offset
vertex-count
arefranges
1+range-offset
key
make-array
1+word-count
:element-type'
unsigned-byte32
unless
membervertex-count'
36
error"LUFT render template ~D has unsupported arity ~D."template-idvertex-count
setf
arefkey0
vertex-count
replacekeyvertices:start11:start2word-start:end2
+word-startword-count
multiple-value-bind
global-idpresent-p
gethashkeytemplate-index
unlesspresent-p
unless
typepglobal-id'
unsigned-byte16
error"LUFT render template vocabulary exceeds 16 bits."
loopforindexfrom1belowdo
vector-push-extend
arefkeyindex
template-words
setf
gethashkeytemplate-index
global-id
valuesglobal-idvertex-count
append-stream
wordsglobal-idsvertex-counts
loopforoffsetfrom0below
lengthwords
byluft:+mesh-instance-word-count+forpacked=
arefwords
+offset3
forlocal-id=
ldb
byte160
packed
forassembly-id=forglobal-id=
arefglobal-idslocal-id
forvertex-count=
arefvertex-countslocal-id
fordestination=
if
=vertex-count3
triangle-wordsquad-words
do
unless
<assembly-idassembly-count
error"LUFT surface assembly ~D is outside the resident vocabulary of ~D entries."assembly-idassembly-count
loopforword-offsetbelow3do
vector-push-extend
arefwords
+offsetword-offset
destination
vector-push-extend
logiorglobal-id
logandpacked#xffff0000
destination
if
=vertex-count3
incftriangle-count
incfquad-count
append-mesh
mesh

Mesh-local template IDs are dense. Resolve each one exactly once, then the large instance streams become a linear copy.

let*
template-count
/
length
luft:surface-mesh-template-rangesmesh
2
global-ids
make-arraytemplate-count:element-type'
unsigned-byte16
vertex-counts
make-arraytemplate-count:element-type'
unsigned-byte8
dotimes
local-idtemplate-count
multiple-value-bind
global-idvertex-count
intern-templatemeshlocal-id
setf
arefglobal-idslocal-id
global-id
arefvertex-countslocal-id
vertex-count
append-stream
luft:surface-mesh-face-instance-wordsmesh
global-idsvertex-counts
append-stream
luft:surface-mesh-band-instance-wordsmesh
global-idsvertex-counts
append-stream
luft:surface-mesh-fan-instance-wordsmesh
global-idsvertex-counts
dolist
meshmeshes
append-meshmesh
%make-render-population
coercetemplate-words'
simple-array
unsigned-byte32
concatenate'
simple-array
unsigned-byte32
triangle-wordsquad-words
triangle-countquad-count
defstruct
mesh-slot
:constructor%make-mesh-slot
:copiernil

One mesh's semantic residency and optional construction-overlay resources.

meshnil
residentnil
lattice-point-buffernil
lattice-point-count0
lattice-point-groupnil
defclassrenderer
device:initarg:device:readerrenderer-device

Chunk key (or any EQL key) to resident MESH-SLOT; SLOT-ORDER is the sorted key list frames draw in.

mesh-slots:initform
make-hash-table:test#'eql
:readerrenderer-mesh-slots
slot-order:initformnil:accessorrenderer-slot-order
camera-buffer:initarg:camera-buffer:accessorrenderer-camera-buffer
material-buffer:initarg:material-buffer:accessorrenderer-material-buffer
layout:initarg:layout:accessorrenderer-layout
vertex-module:initarg:vertex-module:accessorrenderer-vertex-module
fragment-module:initarg:fragment-module:accessorrenderer-fragment-module
pipeline:initarg:pipeline:accessorrenderer-pipeline
shadow-texture:initarg:shadow-texture:accessorrenderer-shadow-texture
shadow-view:initarg:shadow-view:accessorrenderer-shadow-view
shadow-sampler:initarg:shadow-sampler:accessorrenderer-shadow-sampler
shadow-layout:initarg:shadow-layout:accessorrenderer-shadow-layout
shadow-vertex-module:initarg:shadow-vertex-module:accessorrenderer-shadow-vertex-module
shadow-pipeline:initarg:shadow-pipeline:accessorrenderer-shadow-pipeline
player-sdf-layout:initarg:player-sdf-layout:accessorrenderer-player-sdf-layout
player-sdf-bind-group:initarg:player-sdf-bind-group:accessorrenderer-player-sdf-bind-group
player-sdf-vertex-module:initarg:player-sdf-vertex-module:accessorrenderer-player-sdf-vertex-module
player-sdf-fragment-module:initarg:player-sdf-fragment-module:accessorrenderer-player-sdf-fragment-module
player-sdf-pipeline:initarg:player-sdf-pipeline:accessorrenderer-player-sdf-pipeline
lattice-point-layout:initarg:lattice-point-layout:accessorrenderer-lattice-point-layout
lattice-point-vertex-module:initarg:lattice-point-vertex-module:accessorrenderer-lattice-point-vertex-module
lattice-point-fragment-module:initarg:lattice-point-fragment-module:accessorrenderer-lattice-point-fragment-module
lattice-point-pipeline:initarg:lattice-point-pipeline:accessorrenderer-lattice-point-pipeline
sky-layout:initformnil:accessorrenderer-sky-layout
sky-bind-group:initformnil:accessorrenderer-sky-bind-group
sky-fragment-module:initformnil:accessorrenderer-sky-fragment-module
sky-pipeline:initformnil:accessorrenderer-sky-pipeline
color-format:initarg:color-format:readerrenderer-color-format
temporal-p:initarg:temporal-p:readerrenderer-temporal-p
depth-texture:initformnil:accessorrenderer-depth-texture
depth-view:initformnil:accessorrenderer-depth-view
scene-texture:initformnil:accessorrenderer-scene-texture
scene-view:initformnil:accessorrenderer-scene-view
motion-texture:initformnil:accessorrenderer-motion-texture
motion-view:initformnil:accessorrenderer-motion-view
resolved-texture:initformnil:accessorrenderer-resolved-texture
resolved-view:initformnil:accessorrenderer-resolved-view
temporal-scaler:initformnil:accessorrenderer-temporal-scaler
present-layout:initformnil:accessorrenderer-present-layout
present-bind-group:initformnil:accessorrenderer-present-bind-group
present-vertex-module:initformnil:accessorrenderer-present-vertex-module
present-fragment-module:initformnil:accessorrenderer-present-fragment-module
present-pipeline:initformnil:accessorrenderer-present-pipeline
exposure-probe-layout:initformnil:accessorrenderer-exposure-probe-layout
exposure-probe-bind-group:initformnil:accessorrenderer-exposure-probe-bind-group
exposure-probe-texture:initformnil:accessorrenderer-exposure-probe-texture
exposure-probe-view:initformnil:accessorrenderer-exposure-probe-view
exposure-probe-fragment-module:initformnil:accessorrenderer-exposure-probe-fragment-module
exposure-probe-pipeline:initformnil:accessorrenderer-exposure-probe-pipeline
exposure-probe-buffers:initform
:accessorrenderer-exposure-probe-buffers
exposure-probe-submitted:initform
make-array0:element-type'bit
:accessorrenderer-exposure-probe-submitted
exposure-probe-frames:initform
:accessorrenderer-exposure-probe-frames
exposure:initform1.0f0:accessorrenderer-exposure
sampler:initformnil:accessorrenderer-sampler
extent:initformnil:accessorrenderer-extent
render-extent:initformnil:accessorrenderer-render-extent
frame-index:initform0:accessorrenderer-frame-index
previous-view:initformnil:accessorrenderer-previous-view
history-valid-p:initformnil:accessorrenderer-history-valid-p
history-used-p:initformnil:accessorrenderer-history-used-p
defunmetal-temporal-device-p
device
#+darwin(and *temporal-upscaling-p* (typep device 'metal-gpu-device))#-darwin
declare
ignoredevice
#-darwinnil
defundestroy-renderer-targets
dolist
resource
list
renderer-present-bind-grouprenderer
renderer-exposure-probe-bind-grouprenderer
renderer-temporal-scalerrenderer
renderer-resolved-viewrenderer
renderer-resolved-texturerenderer
renderer-motion-viewrenderer
renderer-motion-texturerenderer
renderer-scene-viewrenderer
renderer-scene-texturerenderer
renderer-depth-viewrenderer
renderer-depth-texturerenderer
whenresource
ignore-errors
destroyresource
setf
renderer-present-bind-grouprenderer
nil
renderer-exposure-probe-bind-grouprenderer
nil
renderer-temporal-scalerrenderer
nil
renderer-resolved-viewrenderer
nil
renderer-resolved-texturerenderer
nil
renderer-motion-viewrenderer
nil
renderer-motion-texturerenderer
nil
renderer-scene-viewrenderer
nil
renderer-scene-texturerenderer
nil
renderer-depth-viewrenderer
nil
renderer-depth-texturerenderer
nil
defunrender-scale-extent
extent

Return the even-sized internal render extent for output extent.

mapcarextent
defuncreate-frame-targets
rendererextent
let*
device
renderer-devicerenderer
temporal-p
renderer-temporal-prenderer
render-extent
scaler
andtemporal-p
createdevice
make-temporal-scaler-descriptor:label"luft MetalFX temporal scaler":input-sizerender-extent:output-sizeextent
usage
lambda
baseextra
remove-duplicates
appendbaseextra
depth
createdevice
make-texture-descriptor:label"luft temporal depth":sizerender-extent:dimensions:2d:format:depth32-float:usage
funcallusage'
:render-attachment:texture-binding
andscaler
gpu-temporal-scaler-depth-usagescaler
depth-view
createdevice
make-texture-view-descriptor:texturedepth
scene
createdevice
make-texture-descriptor:label"luft HDR color":sizerender-extent:dimensions:2d:format:rgba16-float:usage
funcallusage'
:render-attachment:texture-binding
andscaler
gpu-temporal-scaler-color-usagescaler
scene-view
createdevice
make-texture-view-descriptor:texturescene
motion
andtemporal-p
createdevice
make-texture-descriptor:label"luft temporal motion":sizerender-extent:dimensions:2d:format:rg16-float:usage
funcallusage'
:render-attachment
gpu-temporal-scaler-motion-usagescaler
motion-view
andmotion
createdevice
make-texture-view-descriptor:texturemotion
resolved
andtemporal-p
createdevice
make-texture-descriptor:label"luft temporal resolve":sizeextent:dimensions:2d:format:rgba16-float:usage
funcallusage'
:texture-binding
gpu-temporal-scaler-output-usagescaler
resolved-view
andresolved
createdevice
make-texture-view-descriptor:textureresolved
present-source-view
orresolved-viewscene-view
present-group
createdevice
make-bind-group-descriptor:label"luft HDR presentation":layout
renderer-present-layoutrenderer
:entries`
:binding0:resource,present-source-view
:binding1:resource,
renderer-samplerrenderer
:binding2:resource,depth-view
:binding3:resource,
renderer-camera-bufferrenderer
exposure-probe-group
createdevice
make-bind-group-descriptor:label"luft exposure probe source":layout
renderer-exposure-probe-layoutrenderer
:entries`
:binding0:resource,present-source-view
:binding1:resource,
renderer-samplerrenderer
setf
renderer-temporal-scalerrenderer
scaler
renderer-depth-texturerenderer
depth
renderer-depth-viewrenderer
depth-view
renderer-scene-texturerenderer
scene
renderer-scene-viewrenderer
scene-view
renderer-motion-texturerenderer
motion
renderer-motion-viewrenderer
motion-view
renderer-resolved-texturerenderer
resolved
renderer-resolved-viewrenderer
resolved-view
renderer-present-bind-grouprenderer
present-group
renderer-exposure-probe-bind-grouprenderer
exposure-probe-group
renderer-extentrenderer
copy-listextent
renderer-render-extentrenderer
copy-listrender-extent
renderer-previous-viewrenderer
nil
renderer-history-valid-prenderer
nil
renderer-history-used-prenderer
nil
renderer
zdefun
mesh-lattice-point-words:zone:luft/prepare-overlay
mesh
"LUFT vertex sites, mesh vertices, and eighth-step boundary-edge samples."
let
points
make-hash-table:test#'eql
result
make-array64:element-type'
unsigned-byte32
:adjustablet:fill-pointer0
templates
luft:surface-mesh-template-vertex-wordsmesh
ranges
luft:surface-mesh-template-rangesmesh
labels
pack-point
xyz

World coordinates are non-negative and comfortably below twenty bits at the eighth-cell scale. One fixnum is a cons-free hash key for the diagnostic point vocabulary.

unless
and
typepx'
unsigned-byte20
typepy'
unsigned-byte20
typepz'
unsigned-byte20
error"LUFT lattice point (~D ~D ~D) exceeds packed range."xyz
logiorx
ashy20
ashz40
remember
xyzmarker-kind
let
key
pack-pointxyz
setf
gethashkeypoints
maxmarker-kind
gethashkeypoints0
sample-axis-edge
axayazbxbybz
cond
and
=ayby
=azbz
/=axbx
loopforxfrom
minaxbx
to
maxaxbx
do
rememberxayaz0
and
=axbx
=azbz
/=ayby
loopforyfrom
minayby
to
maxayby
do
rememberaxyaz0
and
=axbx
=ayby
/=azbz
loopforzfrom
minazbz
to
maxazbz
do
rememberaxayz0
visit-stream
wordsfan-p
loopforinstance-offsetfrom0below
lengthwords
by4forbase-x=
arefwordsinstance-offset
forbase-y=
arefwords
+instance-offset1
forbase-z=
arefwords
+instance-offset2
forpacked=
arefwords
+instance-offset3
fortemplate-id=
ldb
byte160
packed
forvertex-start=
arefranges
*2template-id
forvertex-count=
arefranges
1+
*2template-id
do
loopforvertexfromvertex-startbelow
+vertex-startvertex-count
do
remember
template-coordinatebase-xvertex0
template-coordinatebase-yvertex1
template-coordinatebase-zvertex2
1
loopforvertexfromvertex-startbelow
+vertex-startvertex-count
by3forattributes=
areftemplates
+
*vertex4
3
foredge-mask=
ldb
byte310
attributes
forax=
template-coordinatebase-xvertex0
foray=
template-coordinatebase-yvertex1
foraz=
template-coordinatebase-zvertex2
forbx=
template-coordinatebase-x
1+vertex
0
forby=
template-coordinatebase-y
1+vertex
1
forbz=
template-coordinatebase-z
1+vertex
2
forcx=
template-coordinatebase-x
+vertex2
0
forcy=
template-coordinatebase-y
+vertex2
1
forcz=
template-coordinatebase-z
+vertex2
2
when
logbitp0edge-mask
do
sample-axis-edgebxbybzcxcycz
when
logbitp1edge-mask
do
sample-axis-edgeaxayazcxcycz
when
logbitp2edge-mask
do
sample-axis-edgeaxayazbxbybz
visit-stream
luft:surface-mesh-face-instance-wordsmesh
nil
visit-stream
luft:surface-mesh-band-instance-wordsmesh
nil
visit-stream
luft:surface-mesh-fan-instance-wordsmesh
t
maphash
lambda
pointmarker-kind
vector-push-extend
ldb
byte200
point
result
vector-push-extend
ldb
byte2020
point
result
vector-push-extend
ldb
byte2040
point
result
vector-push-extendmarker-kindresult
points
coerceresult'
simple-array
unsigned-byte32
defun%destroy-mesh-slot
slot
%destroy-resident-population
mesh-slot-residentslot
dolist
resource
list
mesh-slot-lattice-point-groupslot
mesh-slot-lattice-point-bufferslot
whenresource
ignore-errors
destroyresource
values
defunmesh-slot-prepared-mesh
slot

Borrow slot's immutable CPU realization for renderer reconstruction.

%make-prepared-render-mesh
mesh-slot-meshslot
resident-population-population
mesh-slot-residentslot
defun%make-renderer-mesh-slot
renderermesh-or-prepared

Upload one independently retained chunk slot.

mesh-or-prepared may carry worker-built dense population arrays. Construction overlay data is deliberately absent until construction mode asks for it.

let*
prepared
if
typepmesh-or-prepared'prepared-render-mesh
mesh-or-prepared
prepare-render-meshmesh-or-prepared
mesh
prepared-render-mesh-meshprepared
slot
%make-mesh-slot:meshmesh
completed-pnil
unwind-protect
progn
setf
mesh-slot-residentslot
%upload-render-populationrenderer
prepared-render-mesh-populationprepared
setfcompleted-pt
slot
unlesscompleted-p
defunensure-mesh-slot-lattice-points

Create slot's diagnostic overlay on first use, never during normal streaming.

unless
mesh-slot-lattice-point-bufferslot
let*
device
renderer-devicerenderer
camera-buffer
renderer-camera-bufferrenderer
lattice-point-words
mesh-lattice-point-words
mesh-slot-meshslot
lattice-point-count
/
lengthlattice-point-words
4
completed-pnil
flet
stream-buffer
labelwords
let
buffer
createdevice
make-buffer-descriptor:labellabel:size
max16
*4
lengthwords
:usage'
:storage:copy-dst
when
plusp
lengthwords
write-bufferbufferwords
buffer
unwind-protect
progn
setf
mesh-slot-lattice-point-countslot
lattice-point-count
mesh-slot-lattice-point-bufferslot
stream-buffer"luft unique eighth-cell lattice points"lattice-point-words
setf
mesh-slot-lattice-point-groupslot
createdevice
make-bind-group-descriptor:label"luft eighth-cell lattice points":layout
renderer-lattice-point-layoutrenderer
:entries`
:binding0:resource,
mesh-slot-lattice-point-bufferslot
:binding1:resource,camera-buffer
setfcompleted-pt
unlesscompleted-p
dolist
resource
list
mesh-slot-lattice-point-groupslot
mesh-slot-lattice-point-bufferslot
whenresource
ignore-errors
destroyresource
setf
mesh-slot-lattice-point-groupslot
nil
mesh-slot-lattice-point-bufferslot
nil
mesh-slot-lattice-point-countslot
0
slot
defun%destroy-resident-population
resident
whenresident
dolist
resource
list
resident-population-bind-groupresident
resident-population-shadow-bind-groupresident
resident-population-template-bufferresident
resident-population-instance-bufferresident
whenresource
ignore-errors
destroyresource
values
zdefun
%upload-render-population:zone:luft/upload-slot
rendererpopulation
"Build and upload one candidate population without changing RENDERER."
let*
device
renderer-devicerenderer
instance-words
render-population-instance-wordspopulation
template-words
render-population-template-wordspopulation
instance-buffertemplate-bufferbind-groupshadow-bind-group
completed-pnil
flet
stream-buffer
labelwords
let
buffer
createdevice
make-buffer-descriptor:labellabel:size
max16
*4
lengthwords
:usage'
:storage:copy-dst
when
plusp
lengthwords
write-bufferbufferwords
buffer
unwind-protect
progn
setfinstance-buffer
stream-buffer"luft resident site instances"instance-words
template-buffer
stream-buffer"luft canonical site templates"template-words
bind-group
createdevice
make-bind-group-descriptor:label"luft resident site population":layout
renderer-layoutrenderer
:entries`
:binding0:resource,instance-buffer
:binding1:resource,template-buffer
:binding2:resource,
renderer-camera-bufferrenderer
:binding3:resource,
renderer-material-bufferrenderer
:binding4:resource,
renderer-shadow-viewrenderer
:binding5:resource,
renderer-shadow-samplerrenderer
shadow-bind-group
createdevice
make-bind-group-descriptor:label"luft resident shadow population":layout
renderer-shadow-layoutrenderer
:entries`
:binding0:resource,instance-buffer
:binding1:resource,template-buffer
:binding2:resource,
renderer-camera-bufferrenderer
let
resident
%make-resident-populationpopulationinstance-buffertemplate-bufferbind-groupshadow-bind-group
setfcompleted-pt
resident
unlesscompleted-p
dolist
resource
listshadow-bind-groupbind-grouptemplate-bufferinstance-buffer
whenresource
ignore-errors
destroyresource
defun%refresh-renderer-slot-order
let
keys'
loopforkeybeingthehash-keysof
renderer-mesh-slotsrenderer
do
pushkeykeys
setf
renderer-slot-orderrenderer
sortkeys#'<
defunrenderer-set-mesh
rendererkeymesh

Make mesh resident under key, replacing any previous resident mesh.

cdar
defunrenderer-set-meshes
renderermeshes

Transactionally replace the keyed meshes as one visible residency cohort.

meshes is an alist of key to surface mesh. Every GPU slot is created before the renderer's table changes; a failed upload therefore leaves the installed cohort untouched. No frame can interleave with the owner-thread publication.

zdefun
renderer-update-meshes:zone:luft/publish-residency
renderermeshesremoved-keys
"Transactionally replace MESHES and remove REMOVED-KEYS as one cohort."
let
candidatesnil
retirednil
installed-pnil
unwind-protect
progn
dolist
entrymeshes
pushcandidates
setfcandidates
nreversecandidates
dolist
entrycandidates
let
old
gethash
carentry
renderer-mesh-slotsrenderer
setf
gethash
carentry
renderer-mesh-slotsrenderer
cdrentry
whenold
pusholdretired
dolist
keyremoved-keys
unless
assockeycandidates:test#'eql
let
old
gethashkey
renderer-mesh-slotsrenderer
whenold
pusholdretired
remhashkey
renderer-mesh-slotsrenderer
setfinstalled-pt
dolist
slotretired
candidates
unlessinstalled-p
dolist
entrycandidates
defunmake-renderer
devicecolor-formatextent

Create the shared luft pipeline state; meshes arrive via renderer-set-mesh.

let*
temporal-p
target-formats
iftemporal-p'
:rgba16-float:rg16-float
'
:rgba16-float
camera-buffermaterial-bufferlayoutvertex-modulefragment-modulepipelineshadow-textureshadow-viewshadow-samplershadow-layoutshadow-vertex-moduleshadow-pipelineplayer-sdf-layoutplayer-sdf-bind-groupplayer-sdf-vertex-moduleplayer-sdf-fragment-moduleplayer-sdf-pipelinelattice-point-layoutlattice-point-vertex-modulelattice-point-fragment-modulelattice-point-pipelinepresent-layoutpresent-bind-grouppresent-vertex-modulepresent-fragment-modulepresent-pipelinesamplersky-layoutsky-bind-groupsky-fragment-modulesky-pipelineexposure-probe-layoutexposure-probe-bind-groupexposure-probe-textureexposure-probe-viewexposure-probe-fragment-moduleexposure-probe-pipelineexposure-probe-buffersrenderer
completed-pnil
unwind-protect
progn
setfcamera-buffer
createdevice
make-buffer-descriptor:label"luft frame state":size432:usage'
:uniform:copy-dst
material-buffer
let
let
buffer
createdevice
make-buffer-descriptor:label"luft surface assembly descriptors":size
max16
*4
lengthwords
:usage'
:storage:copy-dst
when
plusp
lengthwords
write-bufferbufferwords
buffer
shadow-texture
createdevice
make-texture-descriptor:label"luft sun shadow depth":size:dimensions:2d:format:depth32-float:usage'
:render-attachment:texture-binding
shadow-view
createdevice
make-texture-view-descriptor:textureshadow-texture
shadow-sampler
createdevice
make-sampler-descriptor:label"luft soft shadow comparison sampler":mag-filter:linear:min-filter:linear:mipmap-filter:nearest:compare:less-or-equal
setflayout
createdevice
make-bind-group-layout-descriptor:label"luft mesh layout":entries'
:binding0:type:storage-buffer
:binding1:type:storage-buffer
:binding2:type:uniform-buffer
:binding3:type:storage-buffer
:binding4:type:texture
:binding5:type:sampler
shadow-layout
createdevice
make-bind-group-layout-descriptor:label"luft shadow layout":entries'
:binding0:type:storage-buffer
:binding1:type:storage-buffer
:binding2:type:uniform-buffer
vertex-module
createdevice
make-shader-module-descriptor:label"luft mesh vertex":language:mathematical:code
fragment-module
createdevice
make-shader-module-descriptor:label"luft mesh fragment":language:mathematical:code
pipeline
createdevice
make-render-pipeline-descriptor:label"luft site stream pipeline":layoutlayout:vertex`
:module,vertex-module
:fragment`
:module,fragment-module:targets,
mapcar
lambda
format
`
:format,format
target-formats
:primitive'
:topology:triangle-list
:depth-stencil'
:format:depth32-float:depth-write-enabledt:depth-compare:less
shadow-vertex-module
createdevice
make-shader-module-descriptor:label"luft shadow vertex":language:mathematical:code
shadow-pipeline
createdevice
make-render-pipeline-descriptor:label"luft sun shadow pipeline":layoutshadow-layout:vertex`
:module,shadow-vertex-module
:primitive'
:topology:triangle-list
:depth-stencil'
:format:depth32-float:depth-write-enabledt:depth-compare:less
setfplayer-sdf-layout
createdevice
make-bind-group-layout-descriptor:label"luft player sdf layout":entries'
:binding0:type:uniform-buffer
:binding1:type:texture
:binding2:type:sampler
player-sdf-vertex-module
createdevice
make-shader-module-descriptor:label"luft player sdf vertex":language:mathematical:code
player-sdf-fragment-module
createdevice
make-shader-module-descriptor:label"luft player sdf fragment":language:mathematical:code
player-sdf-pipeline
createdevice
make-render-pipeline-descriptor:label"luft walking player sdf pipeline":layoutplayer-sdf-layout:vertex`
:module,player-sdf-vertex-module
:fragment`
:module,player-sdf-fragment-module:targets,
loopforformatintarget-formatsforfirst=tthennilcollect`
:format,format,@
whenfirst'
:blend:premultiplied-alpha
:primitive'
:topology:triangle-list
:depth-stencil'
:format:depth32-float:depth-write-enablednil:depth-compare:less
player-sdf-bind-group
createdevice
make-bind-group-descriptor:label"luft walking player sdf":layoutplayer-sdf-layout:entries`
:binding0:resource,camera-buffer
:binding1:resource,shadow-view
:binding2:resource,shadow-sampler
setflattice-point-layout
createdevice
make-bind-group-layout-descriptor:label"luft lattice point layout":entries'
:binding0:type:storage-buffer
:binding1:type:uniform-buffer
lattice-point-vertex-module
createdevice
make-shader-module-descriptor:label"luft lattice point vertex":language:mathematical:code
lattice-point-fragment-module
createdevice
make-shader-module-descriptor:label"luft lattice point fragment":language:mathematical:code
lattice-point-pipeline
createdevice
make-render-pipeline-descriptor:label"luft eighth-cell lattice point pipeline":layoutlattice-point-layout:vertex`
:module,lattice-point-vertex-module
:fragment`
:module,lattice-point-fragment-module:targets,
loopforformatintarget-formatsforfirst=tthennilcollect`
:format,format,@
whenfirst'
:blend:premultiplied-alpha
:primitive'
:topology:triangle-list
:depth-stencil'
:format:depth32-float:depth-write-enablednil:depth-compare:less
setfsampler
createdevice
make-sampler-descriptor:label"luft presentation sampler":mag-filter:linear:min-filter:linear
sky-layout
createdevice
make-bind-group-layout-descriptor:label"luft HDR sky layout":entries'
:binding0:type:uniform-buffer
sky-bind-group
createdevice
make-bind-group-descriptor:label"luft HDR sky":layoutsky-layout:entries`
:binding0:resource,camera-buffer
exposure-probe-layout
createdevice
make-bind-group-layout-descriptor:label"luft exposure probe layout":entries'
:binding0:type:texture
:binding1:type:sampler
exposure-probe-texture
createdevice
make-texture-descriptor:label"luft exposure log luminance":size:dimensions:2d:format:rgba8-unorm:usage'
:render-attachment:copy-src
exposure-probe-view
createdevice
make-texture-view-descriptor:textureexposure-probe-texture
exposure-probe-buffers
coerce
looprepeat+exposure-probe-buffer-count+collect
createdevice
make-buffer-descriptor:label"luft exposure readback":size+exposure-probe-byte-count+:usage'
:copy-dst
'vector
setfpresent-layout
createdevice
make-bind-group-layout-descriptor:label"luft presentation layout":entries'
:binding0:type:texture
:binding1:type:sampler
:binding2:type:texture
:binding3:type:uniform-buffer
present-vertex-module
createdevice
make-shader-module-descriptor:label"luft presentation vertex":language:mathematical:code
present-fragment-module
createdevice
make-shader-module-descriptor:label"luft presentation fragment":language:mathematical:code
present-pipeline
createdevice
make-render-pipeline-descriptor:label"luft HDR presentation pipeline":layoutpresent-layout:vertex`
:module,present-vertex-module
:fragment`
:module,present-fragment-module:targets
:format,color-format
:primitive'
:topology:triangle-list
sky-fragment-module
createdevice
make-shader-module-descriptor:label"luft HDR sky fragment":language:mathematical:code
sky-pipeline
createdevice
make-render-pipeline-descriptor:label"luft HDR sky pipeline":layoutsky-layout:vertex`
:module,present-vertex-module
:fragment`
:module,sky-fragment-module:targets,
mapcar
lambda
format
`
:format,format
target-formats
:primitive'
:topology:triangle-list

The sky is drawn inside the scene pass, whose depth attachment geometry subsequently owns. Match that pass without touching its depth.

:depth-stencil'
:format:depth32-float:depth-write-enablednil:depth-compare:always
exposure-probe-fragment-module
createdevice
make-shader-module-descriptor:label"luft exposure probe fragment":language:mathematical:code
exposure-probe-pipeline
createdevice
make-render-pipeline-descriptor:label"luft exposure probe pipeline":layoutexposure-probe-layout:vertex`
:module,present-vertex-module
:fragment`
:module,exposure-probe-fragment-module:targets
:format:rgba8-unorm
:primitive'
:topology:triangle-list
setfrenderer
make-instance'renderer:devicedevice:color-formatcolor-format:temporal-ptemporal-p:camera-buffercamera-buffer:material-buffermaterial-buffer:layoutlayout:vertex-modulevertex-module:fragment-modulefragment-module:pipelinepipeline:shadow-textureshadow-texture:shadow-viewshadow-view:shadow-samplershadow-sampler:shadow-layoutshadow-layout:shadow-vertex-moduleshadow-vertex-module:shadow-pipelineshadow-pipeline:player-sdf-layoutplayer-sdf-layout:player-sdf-bind-groupplayer-sdf-bind-group:player-sdf-vertex-moduleplayer-sdf-vertex-module:player-sdf-fragment-moduleplayer-sdf-fragment-module:player-sdf-pipelineplayer-sdf-pipeline:lattice-point-layoutlattice-point-layout:lattice-point-vertex-modulelattice-point-vertex-module:lattice-point-fragment-modulelattice-point-fragment-module:lattice-point-pipelinelattice-point-pipeline
setf
renderer-present-layoutrenderer
present-layout
renderer-samplerrenderer
sampler
renderer-present-vertex-modulerenderer
present-vertex-module
renderer-present-fragment-modulerenderer
present-fragment-module
renderer-present-pipelinerenderer
present-pipeline
setf
renderer-sky-layoutrenderer
sky-layout
renderer-sky-bind-grouprenderer
sky-bind-group
renderer-sky-fragment-modulerenderer
sky-fragment-module
renderer-sky-pipelinerenderer
sky-pipeline
renderer-exposure-probe-layoutrenderer
exposure-probe-layout
renderer-exposure-probe-texturerenderer
exposure-probe-texture
renderer-exposure-probe-viewrenderer
exposure-probe-view
renderer-exposure-probe-fragment-modulerenderer
exposure-probe-fragment-module
renderer-exposure-probe-pipelinerenderer
exposure-probe-pipeline
renderer-exposure-probe-buffersrenderer
exposure-probe-buffers
renderer-exposure-probe-submittedrenderer
make-array+exposure-probe-buffer-count+:element-type'bit:initial-element0
renderer-exposure-probe-framesrenderer
make-array+exposure-probe-buffer-count+:element-type'
unsigned-byte64
:initial-element0
setfcompleted-pt
renderer
unlesscompleted-p
dolist
resource
append
andexposure-probe-buffers
coerceexposure-probe-buffers'list
listpresent-pipelinepresent-fragment-modulepresent-vertex-modulesamplerpresent-bind-groupsky-pipelinesky-fragment-modulesky-bind-groupsky-layoutexposure-probe-bind-groupexposure-probe-pipelineexposure-probe-fragment-moduleexposure-probe-viewexposure-probe-textureexposure-probe-layoutpresent-layoutlattice-point-pipelinelattice-point-fragment-modulelattice-point-vertex-modulelattice-point-layoutplayer-sdf-bind-groupplayer-sdf-pipelineplayer-sdf-fragment-moduleplayer-sdf-vertex-moduleplayer-sdf-layoutshadow-pipelineshadow-vertex-moduleshadow-layoutshadow-samplershadow-viewshadow-texturepipelinefragment-modulevertex-modulelayoutmaterial-buffercamera-buffer
whenresource
ignore-errors
destroyresource
defundraw-resident-population
passresidentbind-group

Issue the two fixed-arity draws shared by the sun and scene passes.

let*
population
resident-population-populationresident
triangle-count
render-population-triangle-instance-countpopulation
quad-count
render-population-quad-instance-countpopulation
when
plusp
+triangle-countquad-count
set-bind-grouppass0bind-group
when
plusptriangle-count
drawpass3triangle-count
when
pluspquad-count
drawpass6quad-count0triangle-count
defunexposure-probe-average-luminance
bytes

Decode the geometric-mean luminance encoded by the 32x16 GPU probe.

unless
error"LUFT exposure probe returned ~D bytes, expected ~D."
lengthbytes
+exposure-probe-byte-count+
let
sum0d0
loopforindexfrom0below
lengthbytes
by4do
incfsum
arefbytesindex
let*
encoded
/sum
*count255d0
average-log
-
*encoded11.98293d0
9.21034d0
expaverage-log
defunadapted-exposure
currentaverage-luminance

Take one Moppe-style asymmetric eye-adaptation step.

let*
target
max0.55f0
min1.9f0
/0.16f0
coerceaverage-luminance'single-float
rate
if
<targetcurrent
0.10f00.04f0
+current
*
-targetcurrent
rate
defunmaintain-renderer-exposure

Consume the oldest completed probe without waiting for newer GPU work.

let
buffers
renderer-exposure-probe-buffersrenderer
submitted
renderer-exposure-probe-submittedrenderer
frames
renderer-exposure-probe-framesrenderer
oldestnil

A live DEFCLASS update can add this chronology lane to an existing renderer between frames. Preserve its in-flight bits and give those older probes one common age until the next transactional refresh.

unless
=
lengthframes
lengthbuffers
setfframes
make-array
lengthbuffers
:element-type'
unsigned-byte64
:initial-element
renderer-frame-indexrenderer
renderer-exposure-probe-framesrenderer
frames
dotimes
index
lengthbuffers
when
and
=1
arefsubmittedindex
or
nulloldest
<
arefframesindex
arefframesoldest
setfoldestindex
whenoldest
multiple-value-bind
bytesready-p
read-buffer-if-ready
arefbuffersoldest
whenready-p

One adaptation step per rendered frame keeps a CPU pause from collapsing several delayed measurements into one visible jump.

setf
arefsubmittedoldest
0
renderer-exposurerenderer
renderer-exposurerenderer
defunencode-exposure-probe
rendererencodertemporal-p

Reduce unified HDR scene radiance and queue one nonblocking readback.

let*
submitted
renderer-exposure-probe-submittedrenderer

If the GPU is more than three frames behind, keep rendering and retain the last exposure instead of overwriting an in-flight measurement.

when
zerop
arefsubmittedindex
let
pass
begin-render-passencoder
make-render-pass-descriptor:label"luft exposure probe":color-attachments`
:view,
renderer-exposure-probe-viewrenderer
:load-op:clear:store-op:store:clear-value
0.00.00.01.0
whentemporal-p
wait-temporal-scaler-outputpass
renderer-temporal-scalerrenderer
set-pipelinepass
renderer-exposure-probe-pipelinerenderer
set-bind-grouppass0
renderer-exposure-probe-bind-grouprenderer
drawpass3
encodeencoder
make-gpu-copy-texture-to-buffer-command:source
renderer-exposure-probe-texturerenderer
:destination
aref
renderer-exposure-probe-buffersrenderer
index
setf
arefsubmittedindex
1
aref
renderer-exposure-probe-framesrenderer
index
renderer-frame-indexrenderer
defunencode-renderer-frame
rendererencodersurface-textureextentcamera-uniform-data&keyjitterviewplayer-pconstruction-poverlay-encoder
let
shadow-pass
begin-render-passencoder
make-render-pass-descriptor:label"luft sun shadow":color-attachmentsnil:depth-stencil-attachment`
:view,
renderer-shadow-viewrenderer
:depth-load-op:clear:depth-store-op:store:depth-clear-value1.0
set-pipelineshadow-pass
renderer-shadow-pipelinerenderer
dolist
key
renderer-slot-orderrenderer
let
resident
mesh-slot-resident
gethashkey
renderer-mesh-slotsrenderer
draw-resident-populationshadow-passresident
resident-population-shadow-bind-groupresident
end-passshadow-pass
prepare-textureencoder
renderer-shadow-texturerenderer
:texture-binding
let*
temporal-p
renderer-temporal-prenderer
color-view
renderer-scene-viewrenderer
color-attachments
iftemporal-p`
:view,color-view:load-op:clear:store-op:store:clear-value
0.00.00.01.0
:view,
renderer-motion-viewrenderer
:load-op:clear:store-op:store:clear-value
0.00.00.00.0
`
:view,color-view:load-op:clear:store-op:store:clear-value
0.00.00.01.0
pass
begin-render-passencoder
make-render-pass-descriptor:label"luft site streams":color-attachmentscolor-attachments:depth-stencil-attachment`
:view,
renderer-depth-viewrenderer
:depth-load-op:clear:depth-store-op:store:depth-clear-value1.0

The atmosphere is scene-linear world radiance: geometry overwrites it, MetalFX reconstructs it, and the exposure probe meters the same pixels presentation will grade.

set-pipelinepass
renderer-sky-pipelinerenderer
set-bind-grouppass0
renderer-sky-bind-grouprenderer
drawpass3
set-pipelinepass
renderer-pipelinerenderer
dolist
key
renderer-slot-orderrenderer
let
resident
mesh-slot-resident
gethashkey
renderer-mesh-slotsrenderer
draw-resident-populationpassresident
resident-population-bind-groupresident
whenplayer-p
set-pipelinepass
renderer-player-sdf-pipelinerenderer
set-bind-grouppass0
renderer-player-sdf-bind-grouprenderer
drawpass62
whenconstruction-p

Populate at most one diagnostic slot per frame. The overlay is a debugging view, so progressive readiness is preferable to freezing one frame while every resident chunk is scanned.

loopforkeyin
renderer-slot-orderrenderer
forslot=
gethashkey
renderer-mesh-slotsrenderer
unless
mesh-slot-lattice-point-bufferslot
do
set-pipelinepass
renderer-lattice-point-pipelinerenderer
dolist
key
renderer-slot-orderrenderer
let
slot
gethashkey
renderer-mesh-slotsrenderer
when
plusp
mesh-slot-lattice-point-countslot
set-bind-grouppass0
mesh-slot-lattice-point-groupslot
drawpass6
mesh-slot-lattice-point-countslot
whentemporal-p
signal-temporal-scaler-inputspass
renderer-temporal-scalerrenderer
whentemporal-p
let
scaler
renderer-temporal-scalerrenderer
history-valid-p
renderer-history-valid-prenderer
render-extent
renderer-render-extentrenderer
encode-temporal-scaleencoderscaler
renderer-scene-texturerenderer
renderer-depth-texturerenderer
renderer-motion-texturerenderer
renderer-resolved-texturerenderer

jitter is clip-space at the internal scene resolution. MetalFX takes the same offset in input pixels—not output pixels—so using extent here overstates it whenever temporal upscaling is active.

vector
*0.5
firstrender-extent
arefjitter0
*0.5
secondrender-extent
arefjitter1
nothistory-valid-p
setf
renderer-previous-viewrenderer
view
renderer-history-valid-prenderer
t
renderer-history-used-prenderer
history-valid-p
unlesstemporal-p
prepare-textureencoder
renderer-scene-texturerenderer
:texture-binding
prepare-textureencoder
renderer-depth-texturerenderer
:texture-binding
let
present-pass
begin-render-passencoder
make-render-pass-descriptor:label"luft HDR presentation":color-attachments`
:view,surface-texture:load-op:clear:store-op:store:clear-value
0.00.00.01.0
whentemporal-p
wait-temporal-scaler-outputpresent-pass
renderer-temporal-scalerrenderer
set-pipelinepresent-pass
renderer-present-pipelinerenderer
set-bind-grouppresent-pass0
renderer-present-bind-grouprenderer
drawpresent-pass3

Both MetalFX and the direct HDR path publish here. The atelier overlay remains later than tone mapping and glow in either case.

whenoverlay-encoder
funcalloverlay-encoderpresent-pass
end-passpresent-pass

Character motion is presentation time, not a MetalFX capability.

incf
renderer-frame-indexrenderer
renderer
defundestroy-renderer
loopforslotbeingthehash-valuesof
renderer-mesh-slotsrenderer
do
clrhash
renderer-mesh-slotsrenderer
setf
renderer-slot-orderrenderer
nil
dolist
resource
append
coerce
renderer-exposure-probe-buffersrenderer
'list
list
renderer-exposure-probe-pipelinerenderer
renderer-exposure-probe-fragment-modulerenderer
renderer-exposure-probe-viewrenderer
renderer-exposure-probe-texturerenderer
renderer-exposure-probe-layoutrenderer
renderer-sky-pipelinerenderer
renderer-sky-fragment-modulerenderer
renderer-sky-bind-grouprenderer
renderer-sky-layoutrenderer
renderer-present-pipelinerenderer
renderer-present-fragment-modulerenderer
renderer-present-vertex-modulerenderer
renderer-samplerrenderer
renderer-present-layoutrenderer
renderer-lattice-point-pipelinerenderer
renderer-lattice-point-fragment-modulerenderer
renderer-lattice-point-vertex-modulerenderer
renderer-lattice-point-layoutrenderer
renderer-player-sdf-bind-grouprenderer
renderer-player-sdf-pipelinerenderer
renderer-player-sdf-fragment-modulerenderer
renderer-player-sdf-vertex-modulerenderer
renderer-player-sdf-layoutrenderer
renderer-shadow-pipelinerenderer
renderer-shadow-vertex-modulerenderer
renderer-shadow-layoutrenderer
renderer-shadow-samplerrenderer
renderer-shadow-viewrenderer
renderer-shadow-texturerenderer
renderer-pipelinerenderer
renderer-fragment-modulerenderer
renderer-vertex-modulerenderer
renderer-layoutrenderer
renderer-material-bufferrenderer
and
slot-boundprenderer'camera-buffer
renderer-camera-bufferrenderer
whenresource
ignore-errors
destroyresource
setf
renderer-present-pipelinerenderer
nil
renderer-exposure-probe-pipelinerenderer
nil
renderer-exposure-probe-fragment-modulerenderer
nil
renderer-exposure-probe-viewrenderer
nil
renderer-exposure-probe-texturerenderer
nil
renderer-exposure-probe-layoutrenderer
nil
renderer-exposure-probe-buffersrenderer
renderer-exposure-probe-submittedrenderer
make-array0:element-type'bit
renderer-exposure-probe-framesrenderer
renderer-sky-pipelinerenderer
nil
renderer-sky-fragment-modulerenderer
nil
renderer-sky-bind-grouprenderer
nil
renderer-sky-layoutrenderer
nil
renderer-present-fragment-modulerenderer
nil
renderer-present-vertex-modulerenderer
nil
renderer-samplerrenderer
nil
renderer-present-layoutrenderer
nil
renderer-lattice-point-pipelinerenderer
nil
renderer-lattice-point-fragment-modulerenderer
nil
renderer-lattice-point-vertex-modulerenderer
nil
renderer-lattice-point-layoutrenderer
nil
renderer-player-sdf-bind-grouprenderer
nil
renderer-player-sdf-pipelinerenderer
nil
renderer-player-sdf-fragment-modulerenderer
nil
renderer-player-sdf-vertex-modulerenderer
nil
renderer-player-sdf-layoutrenderer
nil
renderer-shadow-pipelinerenderer
nil
renderer-shadow-vertex-modulerenderer
nil
renderer-shadow-layoutrenderer
nil
renderer-shadow-samplerrenderer
nil
renderer-shadow-viewrenderer
nil
renderer-shadow-texturerenderer
nil
renderer-pipelinerenderer
nil
renderer-fragment-modulerenderer
nil
renderer-vertex-modulerenderer
nil
renderer-layoutrenderer
nil
renderer-material-bufferrenderer
nil
renderer-camera-bufferrenderer
nil
values

--------------------------------------------------------------------------- Streaming chunk scenes

A streaming scene is an ordinary authored scene whose solid is split into chunk chains. A bounded square window follows the camera. Each focus change installs the final desired residency first, then remeshes exactly the chunks whose 3 by 3 dependency neighborhoods changed. mesh-chunk's probes into non-resident neighbors signal missing-chunk; immutable worker snapshots answer USE-CHUNK for the captured neighborhood and TREAT-AS-AIR otherwise. The canvas owner publishes replacements and departures as one complete cohort, so no frame observes a mixed seam generation.

defclassstreaming-scene
store:initform
make-hash-table:test#'eql
:readerstreaming-scene-store
loaded:initform
make-hash-table:test#'eql
:readerstreaming-scene-loaded
merged:initform
make-hash-table:test#'eql
:readerstreaming-scene-merged
outstanding:initform
make-hash-table:test#'eql
:readerstreaming-scene-outstanding
staged:initform
make-hash-table:test#'eql
:readerstreaming-scene-staged
cohort:initformnil:accessorstreaming-scene-cohort
removals:initformnil:accessorstreaming-scene-removals
production-errors:initformnil:accessorstreaming-scene-production-errors
frames-per-load:initarg:frames-per-load:initform15:accessorstreaming-scene-frames-per-load
residency-radius:initarg:residency-radius:initform1:accessorstreaming-scene-residency-radius
lod-radius:initarg:lod-radius:initformnil:accessorstreaming-scene-lod-radius
merge-radius:initarg:merge-radius:initformnil:accessorstreaming-scene-merge-radius
far-bevel-width:initarg:far-bevel-width:initform4:accessorstreaming-scene-far-bevel-width
focus:initformnil:accessorstreaming-scene-focus
frame-counter:initform0:accessorstreaming-scene-frame-counter
defstruct
streaming-mesh-snapshot
:constructor%make-streaming-mesh-snapshot
scenekeybevel-widthcoplanar-merge-pneighborhoodstamp

Immutable CPU input for one chunk mesh request.

scenenil:read-onlyt
key0:typeluft:chunk-key:read-onlyt
bevel-widthluft:+mesh-bevel-width+:read-onlyt
coplanar-merge-pnil:typeboolean:read-onlyt
neighborhoodnil:typehash-table:read-onlyt
stampnil:read-onlyt
defclassstreaming-mesh-request
snapshot:initarg:snapshot:readerstreaming-mesh-request-snapshot
defunmake-streaming-scene
scene&key
frames-per-load15
lod-radiusmerge-radius
far-bevel-width4

Wrap scene in bounded camera-driven chunk residency.

When lod-radius is non-NIL, chunks beyond that Chebyshev distance use far-bevel-width. When merge-radius is non-NIL, chunks beyond it additionally dissolve exactly coplanar edges without changing that bevel surface. far-bevel-width names the medial tier in residency state.

let
streaming
make-instance'streaming-scene:solid
scene-solidscene
:material-vocabulary
scene-material-vocabularyscene
:material-cells
scene-material-cellsscene
:material-program
scene-material-programscene
:frames-per-loadframes-per-load:residency-radiusresidency-radius:lod-radiuslod-radius:merge-radiusmerge-radius:far-bevel-widthfar-bevel-width
luft:map-chain-chunks
lambda
keychain
setf
gethashkey
streaming-scene-storestreaming
chain
scene-solidscene
streaming
defunstreaming-scene-keys-near
scenefocus-xfocus-y

Stored chunk keys inside scene's square residency window.

let
radius
streaming-scene-residency-radiusscene
keysnil
loopforkeybeingthehash-keysof
streaming-scene-storescene
when
and
<=radius
<=radius
do
pushkeykeys
sortkeys#'<
defunstreaming-scene-key-distance
keyfocus

Chebyshev chunk distance between key and focus.

defunstreaming-scene-bevel-width-at
scenekeyfocusnear-bevel-width

Select key's mesh tier under focus.

let
lod-radius
streaming-scene-lod-radiusscene
if
andlod-radius
streaming-scene-far-bevel-widthscene
near-bevel-width
defunstreaming-scene-coplanar-p-at
scenekeyfocus

Whether key uses scene's exact coplanar compression under focus.

let
merge-radius
streaming-scene-merge-radiusscene
andfocusmerge-radius
>merge-radius
defunretarget-streaming-scene
sceneproduction-systembevel-widthworld-xworld-y

Batch scene's desired window around a camera position and mesh it once.

when
or
streaming-scene-cohortscene
streaming-scene-removalsscene
let*
focus-key
focus
cons
desired
loaded
streaming-scene-loadedscene
merged
streaming-scene-mergedscene
desired-widths
make-hash-table:test#'eql
desired-merged
make-hash-table:test#'eql
arrivals
remove-if
lambda
key
gethashkeyloaded
desired
departures
loopforkeybeingthehash-keysofloadedunless
memberkeydesired:test#'eql
collectkey
lod-changesnil
dolist
keydesired
let
setf
gethashkeydesired-widths
width
gethashkeydesired-merged
merge-p
multiple-value-bind
old-widthpresent-p
gethashkeyloaded
when
andpresent-p
or
not
eqlold-widthwidth
not
eql
gethashkeymerged
merge-p
pushkeylod-changes
let
residency-changes
appendarrivalsdepartures
changes
appendarrivalsdepartureslod-changes
setf
streaming-scene-focusscene
focus
whenchanges
clrhashloaded
clrhashmerged
dolist
keydesired
setf
gethashkeyloaded
gethashkeydesired-widths
gethashkeymerged
gethashkeydesired-merged
let
affected
remove-if-not
lambda
key
or
memberkeylod-changes:test#'eql
some
lambda
changed
residency-changes
desired
setf
streaming-scene-cohortscene
affected
streaming-scene-removalsscene
departures
dolist
keyaffected
schedule-streaming-scene-meshsceneproduction-systemkey
gethashkeyloaded
t
defunstreaming-scene-neighborhood-keys

Return the loaded 3 by 3 chunk neighborhood observed while meshing key.

let
loopforcandidatebeingthehash-keysof
streaming-scene-loadedscene
whendo
pushcandidatekeys
sortkeys#'<
defunstreaming-scene-mesh-stamp
scenekeybevel-widthcoplanar-merge-p

Name the exact residency and geometry parameters observed by key's mesh.

listbevel-widthcoplanar-merge-p
gethashkey
streaming-scene-loadedscene
defunmake-streaming-mesh-snapshot
scenekeybevel-width

Capture immutable chains for the neighborhood key currently observes.

let
neighborhood
make-hash-table:test#'eql
store
streaming-scene-storescene
coplanar-merge-p
gethashkey
streaming-scene-mergedscene
dolist
setf
gethashneighborneighborhood
gethashneighborstore
%make-streaming-mesh-snapshotscenekeybevel-widthcoplanar-merge-pneighborhood
streaming-scene-mesh-stampscenekeybevel-widthcoplanar-merge-p
defunmesh-streaming-snapshot
snapshot

Mesh one worker-owned residency snapshot without reading owner state.

let*
scene
streaming-mesh-snapshot-scenesnapshot
key
streaming-mesh-snapshot-keysnapshot
neighborhood
streaming-mesh-snapshot-neighborhoodsnapshot
chamfer-stock-function
handler-bind
luft:missing-chunk
lambda
condition
multiple-value-bind
chainpresent-p
gethash
luft:missing-chunk-keycondition
neighborhood
ifpresent-p
invoke-restart'luft:use-chunkchain
invoke-restart'luft:treat-as-air
luft:outside-domain
lambda
condition
declare
ignorecondition
invoke-restart'luft:treat-as-air
let
chain
gethashkeyneighborhood
zone
:luft/rematerialize:value
luft:mesh-chunkchainkey:stock-functionstock-function:chamfer-stock-functionchamfer-stock-function:bevel-width
streaming-mesh-snapshot-bevel-widthsnapshot
:coplanar-merge-p
streaming-mesh-snapshot-coplanar-merge-psnapshot
defunmesh-streaming-chunk
scenekeybevel-width

Synchronously mesh key from the same immutable snapshot workers receive.

defunschedule-streaming-scene-mesh
sceneproduction-systemkeybevel-widthpriority
let*
snapshot
request
make-instance'streaming-mesh-request:keykey:prioritypriority:snapshotsnapshot
ticket
setf
gethashkey
streaming-scene-outstandingscene
ticket
request
defuncurrent-streaming-mesh-request-p
scenerequest
let
snapshot
streaming-mesh-request-snapshotrequest
and
eqscene
streaming-mesh-snapshot-scenesnapshot
equal
streaming-mesh-snapshot-stampsnapshot
streaming-scene-mesh-stampscene
streaming-mesh-snapshot-keysnapshot
streaming-mesh-snapshot-bevel-widthsnapshot
streaming-mesh-snapshot-coplanar-merge-psnapshot
defunaccept-streaming-mesh-result
scenerequestmesh

Stage mesh when request is still the latest description of its chunk.

let*
key
production:production-request-keyrequest
ticket
gethashkey
streaming-scene-outstandingscene
when
eqlticket
production:production-request-ticketrequest
remhashkey
streaming-scene-outstandingscene
when
setf
gethashkey
streaming-scene-stagedscene
consrequestmesh
t
defunready-streaming-scene-meshes

Return the complete current cohort and a readiness flag.

let
cohort
streaming-scene-cohortscene
staged
streaming-scene-stagedscene
active-p
or
streaming-scene-cohortscene
streaming-scene-removalsscene
if
andactive-p
every
lambda
key
let
entry
gethashkeystaged
cohort
values
mapcar
lambda
key
conskey
cdr
gethashkeystaged
cohort
t
valuesnilnil
defunpublish-ready-streaming-scene

Install a complete current mesh cohort at the canvas-owner boundary.

multiple-value-bind
meshesready-p
whenready-p
renderer-update-meshesrenderermeshes
streaming-scene-removalsscene
dolist
entrymeshes
remhash
carentry
streaming-scene-stagedscene
setf
streaming-scene-cohortscene
nil
streaming-scene-removalsscene
nil
lengthmeshes
defundrain-streaming-scene-production
scenerendererproduction-system&key
limit2

Drain and publish bounded worker results on the canvas owner thread.

looprepeatlimitdo
multiple-value-bind
resultpresent-p
unlesspresent-p
let*
request
production:production-result-requestresult
key
production:production-request-keyrequest
ticket
gethashkey
streaming-scene-outstandingscene
when
eqlticket
production:production-request-ticketrequest
if
production:production-result-conditionresult
progn
remhashkey
streaming-scene-outstandingscene
pushresult
streaming-scene-production-errorsscene
error"LUFT mesh production for chunk ~D failed: ~A"key
production:production-result-conditionresult
accept-streaming-mesh-resultscenerequest
production:production-result-valueresult
defunlandscape-hash-reading
xyseedsalt

Return a stable coordinate reading in [-1, 1].

let
value
logand#xffffffff
+seed
*x374761393
*y668265263
*salt2246822519
setfvalue
logand#xffffffff
*
logxorvalue
ashvalue-13
1274126177
-
*2.0d0
/
logand#xffffffff
logxorvalue
ashvalue-16
#xffffffff
1.0d0
defunsmooth-landscape-reading
reading
*readingreading
-3.0d0
*2.0d0reading
defuninterpolate-landscape-reading
leftrightamount
+left
*
-rightleft
amount
defunlandscape-value-noise
xyperiodseedsalt

Sample stable smooth value noise without allocating terrain objects.

let*
sample-x
/x
coerceperiod'double-float
sample-y
/y
coerceperiod'double-float
cell-x
floorsample-x
cell-y
floorsample-y
far
defunlandscape-ramp
lowhighreading
smooth-landscape-reading
max0.0d0
min1.0d0
/
-readinglow
-highlow
defunhighland-landscape-height
xysize&key
seed121

Height of the authored highland at X,Y.

The invariant is that every reading is a pure function of X, Y, size, and seed. Low-frequency domain warping bends a zero-contour into mountain chains; independent fields add foothills, a basin, a river valley, and a terraced upland instead of repeating one periodic profile.

let*
warp-x
+x
*23.0d0
warp-y
+y
*23.0d0
continent
landscape-value-noisewarp-xwarp-y211seed0
fold
abs
landscape-value-noisewarp-xwarp-y103seed7
ridge
expt
max0.0d0
-1.0d0
*1.45d0fold
1.55d0
mountain-country
+0.3d0
*0.7d0
foothills
landscape-value-noisewarp-xwarp-y47seed2
detail
western-distance
sqrt
+
expt
/
-x
*size0.27d0
*size0.31d0
2
expt
/
-y
*size0.58d0
*size0.40d0
2
eastern-distance
sqrt
+
expt
/
-x
*size0.72d0
*size0.24d0
2
expt
/
-y
*size0.30d0
*size0.30d0
2
massif
max
expt
max0.0d0
-1.0d0western-distance
1.4d0
*0.78d0
expt
max0.0d0
-1.0d0eastern-distance
1.3d0
river-centre
+
*size0.46d0
*size0.13d0
river-width
+7.0d0
*size0.018d0
river
expt
max0.0d0
-1.0d0
/
abs
-yriver-centre
river-width
2
basin-x
*size0.24d0
basin-y
*size0.73d0
basin-distance
sqrt
+
expt
-xbasin-x
2
expt
-ybasin-y
2
basin
expt
max0.0d0
-1.0d0
/basin-distance
*size0.22d0
2
raw
-
+10.0d0
*5.0d0continent
*30.0d0ridgemountain-country
*massif
+22.0d0
*10.0d0ridge
*4.5d0foothills
*2.6d0detail
*9.0d0river
*7.0d0basin
plateau
landscape-ramp0.18d00.62d0
+
*0.55d0
/
-
+xy
size
size
terraced
*3.0d0
round
/raw3.0d0
height
interpolate-landscape-readingrawterraced
*0.35d0plateau
max2
min72
roundheight
defunbuild-highland-lookout
builderxybase&key
citadel-pnil

Build one sparse limestone lookout; citadel-p makes the regional anchor.

let
platform-radius
ifcitadel-p135
tower-inner
ifcitadel-p52
tower-outer
ifcitadel-p84
tower-height
ifcitadel-p1510
scene-builder-discbuilderxyplatform-radius
1-base
base:architecture-pt
scene-builder-ringbuilderxytower-innertower-outer
1+base
+basetower-height
:architecture-pt
scene-builder-ringbuilderxytower-inner
1+tower-outer
+basetower-height1
+basetower-height2
:architecture-pt
unlesscitadel-p
scene-builder-discbuilderxytower-outer
+basetower-height2
+basetower-height2
:architecture-pt
whencitadel-p
scene-builder-carve-archbuilderx
+base1
+base5
2
cons
-ytower-outer
+ytower-outer
:axis:x
scene-builder-carve-archbuildery
+base1
+base5
2
cons
-xtower-outer
+xtower-outer
:axis:y
defunmake-highland-sanctuary-scene
&key
horizontal-bits9
seed121
streaming-pt

Make a large varied landscape with mountain chains and sparse ruins.

The default 512 by 512 world spans sixty-four luft chunks. streaming-p wraps it in a seven-by-seven camera-driven window: full bevel nearby, medial terrain in the middle ring, and exact coplanar compression in the outer ring.

let*
builder
make-scene-builder:horizontal-bitshorizontal-bits
size
ash1horizontal-bits
dotimes
xsize

Deliberately sparse, asymmetrical anchors replace the old tower in every chunk. Their different scales make travel across the terrain legible.

dolist
landmark'
0.27d00.29d0nil
0.71d00.68d0t
0.79d00.24d0nil
destructuring-bind
fraction-xfraction-ycitadel-p
landmark
let*
x
round
*sizefraction-x
y
round
*sizefraction-y
base
build-highland-lookoutbuilderxybase:citadel-pcitadel-p
let
ifstreaming-p
make-streaming-scenescene:residency-radius3:lod-radius1:merge-radius2
scene