luv

Workshop wiki

player-body-shaders.lisp

luvcraft/player-body-shaders.lisp

system luvcraft/core · 19 definitions · on GitHub

The player's body as an analytic field.

The complete neutral avatar below is the same kind of object as an SDF cat or gnome: torso, head, limbs, and hands are one smooth signed-distance field. First person normally sees only the view-local arm slice of that body. Its palms still come from BODY.LISP, so walking bob, breathing, and holding a phone remain authored once; a lower-screen proxy merely launches the rays which find the round sleeves, wrists, and hands.

in-package#:luvcraft.shaders
defparameter*player-sdf-arm-radius*0.040"Radius of the player's SDF forearms in view-space cells."
defparameter*player-sdf-hand-size*0.045"Overall radius of the player's SDF hands."
defparameter*player-sdf-sleeve-fraction*0.74"Fraction of shoulder-to-palm reach covered by the sleeve."
defparameter*player-sdf-shoulder-spread*0.36"Half the separation between the viewmodel shoulders."
defparameter*player-sdf-smoothing*0.020"Width of the soft SDF weld between each wrist and hand."
macrolet
define-player-body-knob
nameplacequantityminimummaximumsteplabel
`
luvcraft:define-knob,name
:group:player:label,label:quantity
:quantity,quantity:unit,
if
eqquantity:figure-proportion
:one:cell
:minimum,minimum:maximum,maximum:step,step
,place
define-player-body-knobplayer-sdf-arm-radius*player-sdf-arm-radius*:figure-extent0.0350.140.005"SDF arm radius"
define-player-body-knobplayer-sdf-hand-size*player-sdf-hand-size*:figure-extent0.0450.170.005"SDF hand size"
define-player-body-knobplayer-sdf-sleeve-fraction*player-sdf-sleeve-fraction*:figure-proportion0.250.920.02"SDF sleeve length"
define-player-body-knobplayer-sdf-shoulder-spread*player-sdf-shoulder-spread*:figure-extent0.160.550.01"SDF shoulder spread"
define-player-body-knobplayer-sdf-smoothing*player-sdf-smoothing*:figure-extent0.00.100.005"SDF body smoothing"

--------------------------------------------------------------------- Shared field vocabulary and the complete avatar.

define-shader-functionplayer-sdf-smooth-union
first-distancesecond-distanceradius
let*
safe-radius
maxradius1e-5
blend
clamp
+0.5
*0.5
/
-second-distancefirst-distance
safe-radius
0.01.0
-
mixsecond-distancefirst-distanceblend
*radius
*blend
-1.0blend
define-shader-functionplayer-sdf-ellipsoid-distance
pointcenterradii
let*
offset
/
-pointcenter
radii
gradient
/
*outer
-outer1.0
maxgradient1e-6
define-shader-functionplayer-sdf-capsule-distance
pointbeginningendradius
let*
offset
-pointbeginning
axis
-endbeginning
fraction
-radius
define-shader-functionplayer-avatar-distance
point
"The player's complete neutral body, feet at y=0 and forward along +z."
let*
torso
player-sdf-ellipsoid-distancepoint
vec30.01.150.0
vec30.300.460.19
head
mirrored
vec3
abs
swizzlepoint:x
swizzlepoint:y
swizzlepoint:z
leg
player-sdf-capsule-distancemirrored
vec30.140.100.0
vec30.140.780.0
0.115
arm
player-sdf-capsule-distancemirrored
vec30.311.430.0
vec30.420.860.03
player-sdf-arm-radius
hand
player-sdf-ellipsoid-distancemirrored
vec30.420.800.05
vec3player-sdf-hand-size
*player-sdf-hand-size0.86
*player-sdf-hand-size1.08

--------------------------------------------------------------------- The first-person slice of the same limb vocabulary.

define-shader-functionplayer-viewmodel-sleeve-distance
pointpalmside
let*
cuff
mixshoulderpalmplayer-sdf-sleeve-fraction
player-sdf-capsule-distancepointshouldercuffplayer-sdf-arm-radius
define-shader-functionplayer-viewmodel-skin-distance
pointpalmside
let*
wrist
mixshoulderpalm
-player-sdf-sleeve-fraction0.035
bare
player-sdf-capsule-distancepointwristpalm
*player-sdf-arm-radius0.90
hand
player-sdf-ellipsoid-distancepointpalm
vec3player-sdf-hand-size
*player-sdf-hand-size0.70
*player-sdf-hand-size1.08

The thumb is part of the hand-size vocabulary, not a fixed bead: tuning the palm in the metabar preserves a recognizable hand.

thumb-center
+palm
vec3
*side
*player-sdf-hand-size-0.86
*player-sdf-hand-size0.067
*player-sdf-hand-size-0.20
thumb
player-sdf-ellipsoid-distancepointthumb-center
vec3
*player-sdf-hand-size0.57
*player-sdf-hand-size0.63
*player-sdf-hand-size0.73
player-sdf-smooth-unionbareplayer-sdf-smoothing
define-shader-functionplayer-viewmodel-distance
pointleft-palmright-palm
let*
left-sleeve
right-sleeve
left-skin
right-skin
min
minleft-sleeveright-sleeve
minleft-skinright-skin
define-shader-functionplayer-viewmodel-albedo
pointleft-palmright-palm
let*
skin-nearer
stepskinsleeve
sleeve-color
vec30.0750.200.30
skin-color
vec30.740.430.29
mixsleeve-colorskin-colorskin-nearer
define-shader-functionplayer-viewmodel-normal
pointleft-palmright-palm
let*
reach0.0012
a
vec31.0-1.0-1.0
b
vec3-1.0-1.01.0
c
vec3-1.01.0-1.0
d
vec31.01.01.0
normalize
+
+
*a
player-viewmodel-distance
+point
*areach
left-palmright-palm
*b
player-viewmodel-distance
+point
*breach
left-palmright-palm
+
*c
player-viewmodel-distance
+point
*creach
left-palmright-palm
*d
player-viewmodel-distance
+point
*dreach
left-palmright-palm

--------------------------------------------------------------------- Lower-screen proxy and marcher.

define-shader-methodshader-specification-forplayer-body-sdf-vertex-specification
role
eql:player-body-sdf
stage
eql:vertex
:stage:vertex:inputs
quad-corner:vec3:location0
left-palm-input:vec4:location1
right-palm-input:vec4:location2
:outputs
clip-position:vec4:built-in:position
proxy-view-position:vec3:location0
left-palm-output:vec4:location1
right-palm-output:vec4:location2
:resources
frame-state:uniform-block:set0:binding2:members#.*frame-uniform-members*
let*
corner-x
-
*
swizzlequad-corner:x
2.0
1.0

In this projection positive clip y is down the presented image. The arms never need the top fifth of the screen.

corner-y
-
*
swizzlequad-corner:y
1.18
0.18
x-scale
representation
swizzleprojection-vector:x
y-scale
representation
swizzleprojection-vector:y
view-position
vec3
/corner-xx-scale
-
/corner-yy-scale
1.0
set-outputclip-position
vec4corner-xcorner-y0.01.0
set-outputproxy-view-positionview-position
set-outputleft-palm-outputleft-palm-input
set-outputright-palm-outputright-palm-input
define-shader-methodshader-specification-forplayer-body-sdf-fragment-specification
role
eql:player-body-sdf
stage
eql:fragment
:stage:fragment:inputs
proxy-view-position:vec3:location0
left-palm-input:vec4:location1
right-palm-input:vec4:location2
:outputs
color-output:vec4:location0
:resources
frame-state:uniform-block:set0:binding2:members#.*frame-uniform-members*
let*
left-palm
swizzleleft-palm-input:xyz
right-palm
swizzleright-palm-input:xyz
ray
normalizeproxy-view-position
travel
counted-fold
march52.0ray-distance0.035
point
*raytravel
surface-distance
player-viewmodel-distancepointleft-palmright-palm
coverage
-1.0
step0.0028surface-distance
local-normal
player-viewmodel-normalpointleft-palmright-palm
right
representation
swizzleright-vector:xyz
up
forward
representation
swizzleforward-vector:xyz
normal
+
*right
swizzlelocal-normal:x
+
*up
swizzlelocal-normal:y
*forward
swizzlelocal-normal:z
albedo
player-viewmodel-albedopointleft-palmright-palm
sun-direction
representation
swizzlesun-vector:xyz
sun-color
representation
swizzlesun-color-vector:xyz
ambient
representation
swizzleambient-vector:xyz
lambert
dotnormalsun-direction
wrapped
max0.0
/
+lambert0.42
1.42
view-facing
max0.0
dotlocal-normal
*ray-1.0
rim
expt
-1.0view-facing
3.0
halfway
normalize
-sun-direction
+
*right
swizzleray:x
+
*up
swizzleray:y
*forward
swizzleray:z
specular
*0.16
expt
max0.0
dotnormalhalfway
28.0
illumination
+
*ambient0.90
*sun-color
+0.16
*wrapped0.95
radiance
+
+
*albedoillumination
*sun-color
*specularcoverage
*
vec30.320.560.76
*rim0.08
set-outputcolor-output
vec4
*radiancecoverage
coverage