@@ -22,33 +22,33 @@ in vec3 v_color;
2222in float v_alpha;
2323in float v_peakRadiance;
2424in float v_psfRadius;
25- in float v_pointSize;
2625
2726void main(void )
2827{
2928 // Pixel offset from the centre of the point sprite (in screen pixels).
30- vec2 d = (gl_PointCoord .xy - vec2 (0.5 )) * v_pointSize;
31- float px = length (d) / max (pointScale, 1e-6 );
29+ // gl_PointSize was set to 2 * v_psfRadius * pointScale in the vertex
30+ // shader, so length(gl_PointCoord - 0.5) * 2 * v_psfRadius equals the
31+ // distance from the sprite centre in unscaled pixels (pointScale
32+ // cancels out).
33+ float px = length (gl_PointCoord .xy - vec2 (0.5 )) * 2.0 * v_psfRadius;
3234
3335 // intensity = clamp(((peak^0.4 / px - a) * b)^2.5, 0, peak)
34- if (px <= 0.0 || px >= v_psfRadius)
35- discard ;
36-
37- float base = pow (max (v_peakRadiance, 1e-6 ), 0.4 ) / px - psfA;
38- if (base <= 0.0 )
36+ if (px >= v_psfRadius)
3937 discard ;
4038
39+ // p04 = pow(v_peakRadiance, 0.4) was already computed in the vertex
40+ // shader as v_psfRadius * psfA -- recover it with a multiply instead
41+ // of paying for a pow per fragment.
42+ float p04 = v_psfRadius * psfA;
43+ float base = p04 / px - psfA;
4144 float val = pow (base * psfB, 2.5 );
42- val = clamp (val, 0.0 , v_peakRadiance);
43-
44- // Cap per-fragment output radiance at v_alpha (hue-preserving): the
45- // PSF center can otherwise dump arbitrarily large values into the
46- // additive accumulation, oversaturating any single pixel. Scaling
47- // by v_alpha is what actually makes the C++-side alpha fade visible
48- // — without it, premultiplied v_color and the inverse-max clamp
49- // cancel out, defeating the fade.
50- float maxCh = max (max (v_color.r, v_color.g), v_color.b);
51- val = min (val, v_alpha / max (maxCh, 1e-6 ));
52-
53- fragColor = vec4 (v_color * val, 1.0 );
45+ val = min (val, v_peakRadiance);
46+
47+ // Clamp each channel of v_color * val to 1 BEFORE applying the
48+ // fade alpha so the bleached-white centre of a colored (e.g.
49+ // blue) star stays white through the fade, instead of reverting
50+ // to its underlying tint once v_alpha drops the per-channel value
51+ // back below saturation.
52+ vec3 clampedColor = min (vec3 (1.0 ), v_color * val);
53+ fragColor = vec4 (clampedColor * v_alpha, 1.0 );
5454}
0 commit comments