mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 20:03:44 +00:00
a836a96d13
The dust emitter's box fully encloses the arena, so motes drifted through the pitch and hazed the surfaces the player is trying to read. Fade each mote by the Chebyshev distance of its world-space origin outside the play volume, taken from MODEL_MATRIX's translation column so it is unaffected by the billboard rewrite of VERTEX. Motes inside the box are fully hidden and fade in over arena_clear_distance beyond it, so the effect reads as weather drifting around the station rather than through the match. Extents default to ArenaBoundary's play volume and are exposed as uniforms. Also adds the missing .uid sidecar for the shader.
69 lines
3.1 KiB
Plaintext
69 lines
3.1 KiB
Plaintext
shader_type spatial;
|
|
render_mode blend_mix, depth_draw_never, cull_disabled, specular_disabled;
|
|
|
|
uniform sampler2D albedo_tex : source_color;
|
|
uniform sampler2D depth_tex : hint_depth_texture, filter_linear_mipmap;
|
|
uniform vec3 core_bias_color : source_color = vec3(1.0, 0.6, 0.85);
|
|
uniform float core_bias_amount : hint_range(0.0, 1.0) = 0.35;
|
|
uniform float emission_strength : hint_range(0.0, 5.0) = 2.5;
|
|
uniform float soft_fade_distance : hint_range(0.0, 5.0) = 1.0;
|
|
// Arena play volume (world space) this weather effect must stay clear of —
|
|
// see ArenaBoundary.INNER_HALF_X/INNER_HALF_Z/INNER_HEIGHT. Dust is fully
|
|
// hidden inside that box and fades in over arena_clear_distance beyond it,
|
|
// so it reads as drifting around the station rather than through the pitch.
|
|
uniform vec3 arena_half_extents = vec3(12.0, 6.0, 18.0);
|
|
uniform vec3 arena_centre = vec3(0.0, 6.0, 0.0);
|
|
uniform float arena_clear_distance : hint_range(0.0, 10.0) = 2.0;
|
|
|
|
varying float v_flicker;
|
|
varying float v_arena_fade;
|
|
|
|
void vertex() {
|
|
// true billboard: strip rotation from the per-instance modelview, keep translation + scale
|
|
mat4 mv = MODELVIEW_MATRIX;
|
|
mv[0].xyz = vec3(length(mv[0].xyz), 0.0, 0.0);
|
|
mv[1].xyz = vec3(0.0, length(mv[1].xyz), 0.0);
|
|
mv[2].xyz = vec3(0.0, 0.0, length(mv[2].xyz));
|
|
VERTEX = (mv * vec4(VERTEX, 1.0)).xyz;
|
|
|
|
// INSTANCE_CUSTOM.x is GPUParticles3D's per-particle random seed, baked at spawn
|
|
float seed = INSTANCE_CUSTOM.x;
|
|
float flicker_hash = fract(sin((seed + floor(TIME * 6.0)) * 127.1) * 43758.5453);
|
|
v_flicker = 0.85 + 0.15 * flicker_hash;
|
|
|
|
// MODEL_MATRIX's translation column is this particle's world-space
|
|
// origin (pre-billboard, so unaffected by the VERTEX rewrite above).
|
|
// Chebyshev (box) distance outside arena_half_extents, in metres.
|
|
vec3 particle_pos = MODEL_MATRIX[3].xyz;
|
|
vec3 outside = abs(particle_pos - arena_centre) - arena_half_extents;
|
|
float outside_dist = max(max(outside.x, outside.y), outside.z);
|
|
v_arena_fade = smoothstep(0.0, arena_clear_distance, outside_dist);
|
|
}
|
|
|
|
void fragment() {
|
|
// fake a puff/sphere normal from local UV so a camera-facing billboard can still catch directional light;
|
|
// the quad is billboarded to face the camera in vertex(), so this normal is already view-space aligned
|
|
vec2 centered = UV * 2.0 - 1.0;
|
|
float r2 = dot(centered, centered);
|
|
float mask = clamp(1.0 - r2, 0.0, 1.0);
|
|
NORMAL = normalize(vec3(centered, sqrt(max(mask, 0.001))));
|
|
|
|
vec4 tex = texture(albedo_tex, UV);
|
|
ALBEDO = tex.rgb * mix(vec3(1.0), core_bias_color, core_bias_amount);
|
|
EMISSION = core_bias_color * tex.rgb * emission_strength * 0.15;
|
|
ALPHA = tex.a * COLOR.a * mask * v_arena_fade;
|
|
|
|
float raw_depth = texture(depth_tex, SCREEN_UV).r;
|
|
vec3 ndc = vec3(SCREEN_UV * 2.0 - 1.0, raw_depth);
|
|
vec4 view_pos = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
|
|
view_pos.xyz /= view_pos.w;
|
|
float scene_depth = -view_pos.z;
|
|
float particle_depth = -VERTEX.z;
|
|
ALPHA *= clamp((scene_depth - particle_depth) / soft_fade_distance, 0.0, 1.0);
|
|
}
|
|
|
|
void light() {
|
|
float ndotl = clamp(dot(NORMAL, LIGHT), 0.0, 1.0);
|
|
DIFFUSE_LIGHT += LIGHT_COLOR * ndotl * ALBEDO * emission_strength * v_flicker * ATTENUATION;
|
|
}
|