36 lines
1.4 KiB
Plaintext
36 lines
1.4 KiB
Plaintext
shader_type spatial;
|
|
// Flat crowd sprite. Each instance is oriented at build time to face the arena centre
|
|
// (see crowd_billboards.gd) — NOT the camera — so spectators on different segments of
|
|
// the ring face inward toward the action, like a real stand. Unshaded (the sheet was
|
|
// baked with lighting), alpha-tested (no transparency sorting across hundreds of
|
|
// quads), nearest-filtered for a crisp PS1 look that matches the ps1_filter effect.
|
|
render_mode unshaded, cull_disabled, shadows_disabled, depth_draw_opaque;
|
|
|
|
uniform sampler2D sheet : source_color, filter_nearest;
|
|
uniform int hframes = 8;
|
|
uniform float fps = 10.0;
|
|
uniform float alpha_clip = 0.4;
|
|
|
|
varying flat float v_frame;
|
|
varying flat vec3 v_tint;
|
|
|
|
void vertex() {
|
|
// Per-instance clap phase (0..1) and tint are packed into the MultiMesh custom data.
|
|
// The instance transform already carries the inward facing, so no billboard maths.
|
|
float phase = INSTANCE_CUSTOM.x;
|
|
v_tint = INSTANCE_CUSTOM.yzw;
|
|
v_frame = floor(mod(TIME * fps + phase * float(hframes), float(hframes)));
|
|
}
|
|
|
|
void fragment() {
|
|
// Sheet is two rows: top = front, bottom = back. Show the back when the camera is
|
|
// behind the spectator (they're facing into the arena, away from us).
|
|
float u = (UV.x + v_frame) / float(hframes);
|
|
float v = UV.y * 0.5 + (FRONT_FACING ? 0.0 : 0.5);
|
|
vec4 c = texture(sheet, vec2(u, v));
|
|
if (c.a < alpha_clip) {
|
|
discard;
|
|
}
|
|
ALBEDO = c.rgb * v_tint;
|
|
}
|