radiance: margin inside the glass rim; haloed corona sparks and glints (oversized soft-falloff points)

This commit is contained in:
dangrubbb
2026-10-24 09:36:45 -04:00
parent aac2bdf2e6
commit fcc1326e86

View File

@ -98,7 +98,8 @@ float lifeAlpha(float x) {
float layerR(uint idx) {
float k = h01(idx * 8u + 5u);
float u = h01(idx * 8u + 4u);
return k < 0.5 ? mix(0.94, 1.0, u) : mix(0.4, 0.94, u);
// both stay clear of the glass at r = 1, leaving a margin around the rim
return k < 0.5 ? mix(0.86, 0.925, u) : mix(0.4, 0.85, u);
}
// A drifting ridge field: density peaks along thin curved sheets, which cut the sphere as ribbons.
float density(vec3 dir, float t) {
@ -372,7 +373,7 @@ void main() {
}
float r = length(pos);
vec3 n = pos / max(r, 1e-4);
float surf = step(0.9, rt);
float surf = step(0.855, rt);
// the cursor: the 2D fluid under the particle's screen position, pushed into 3D
vec3 bp = bodyToView(pos);
@ -403,7 +404,7 @@ void main() {
n = pos / max(r, 1e-4);
vel -= n * max(dot(vel, n), 0.0) * smoothstep(rt - 0.05, rt + 0.01, r);
r = mix(r, rt, 1.0 - exp(-uDt * 1.6));
pos = n * min(r, 0.985);
pos = n * min(r, 0.93);
stir = max(stir * exp(-uDt * 1.2), clamp(fm * front * 1.5, 0.0, 1.5));
oPos = vec4(pos, stir);
@ -425,6 +426,7 @@ uniform float uR; // css px
uniform float uDpr;
out vec4 vColor;
out float vGlow;
out float vCore;
void main() {
uint idx = uint(gl_VertexID);
@ -458,17 +460,17 @@ void main() {
size = mix(1.5 + r.y * 1.5 + n * 1.3, 2.8 + r.w * 2.4, spark);
float tw = 0.5 + 0.5 * sin(t * (1.2 + r.x * 2.5) + r.w * 40.0);
col.a *= mix(1.0, mix(0.4, 1.0, tw), spark);
vGlow = spark;
vGlow = spark * 0.5;
// the far side reads dimmer through the glass, and so do particles hanging deep in the volume
// (it also thins the crowd that edge-on particles would form along the limb)
col.a *= mix(0.2, 1.0, smoothstep(-0.2, 0.6, bp.z));
col.a *= mix(0.65, 1.0, step(0.9, rt));
col.a *= mix(0.65, 1.0, step(0.855, rt));
col.a *= lifeAlpha(lt);
// stirred particles heat up: brighter, hotter, a little bigger
col.rgb = mix(col.rgb, vec3(1.0, 0.8, 0.55), clamp(stir * 0.3, 0.0, 0.4));
col.a = min(1.0, col.a * (1.0 + stir * 0.5));
size *= 1.0 + stir * 0.8;
vGlow = max(vGlow, clamp(stir * 0.8, 0.0, 1.0));
size *= 1.0 + stir * 0.5;
vGlow = max(vGlow, clamp(stir * 0.2, 0.0, 0.25));
} else {
P p = corona(idx);
vec2 disp = s0.xy;
@ -491,7 +493,10 @@ void main() {
vec2 px = uCenter + vec2(vp.x, -vp.y) * uR;
gl_Position = vec4(px.x / uView.x * 2.0 - 1.0, 1.0 - px.y / uView.y * 2.0, 0.0, 1.0);
gl_PointSize = size * sc * uDpr * persp;
// glowing points are drawn larger so the halo has room around the core
float glowScale = 1.0 + vGlow * 2.4;
gl_PointSize = size * sc * uDpr * persp * glowScale;
vCore = 1.0 / glowScale;
vColor = col;
}
`;
@ -499,12 +504,12 @@ void main() {
const FRAG_PARTICLES = `${HEAD}
in vec4 vColor;
in float vGlow;
in float vCore; // the core's share of the point's width; the rest is room for the halo
out vec4 o;
void main() {
vec2 c = gl_PointCoord - 0.5;
float r = length(c);
float core = smoothstep(0.5, 0.18, r);
float halo = vGlow * smoothstep(0.5, 0.0, r) * 0.55;
float rr = length(gl_PointCoord - 0.5) * 2.0; // 0 at the centre, 1 at the edge of the point
float core = 1.0 - smoothstep(0.36 * vCore, vCore, rr);
float halo = vGlow * pow(max(1.0 - rr, 0.0), 2.2) * 0.55;
float a = vColor.a * clamp(core + halo, 0.0, 1.0);
if (a < 0.01) discard;
o = vec4(vColor.rgb * a, a);