From 6b375ea9835b0134595a4fcd9553b68951d3b5f6 Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Tue, 13 Oct 2026 08:33:03 +0200 Subject: [PATCH] sun: add configurable warm corona glow --- config.js | 11 ++++++++++- vendor/clouds3d.js | 44 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/config.js b/config.js index 9eaad2e..fb484e7 100644 --- a/config.js +++ b/config.js @@ -650,9 +650,18 @@ window.CONFIG = { // scene lighting are NOT scaled with it. sun: { angularRadius: 0.0279, // 6x the physical 0.00465 rad - brightness: 1.8 // sun disc/halo gain + brightness: 2.1, // sun disc/glow gain + glow: { + enabled: true, + core: 1.15, // bright inner corona + inner: 0.95, // warm near halo + outer: 0.38, // soft far halo + outerRadius: 11.0, // outer halo radius in sun-disc radii + color: [1.00, 0.78, 0.36] + } // angularRadius: 0.0558, brightness: 1.0 // angularRadius: 0.0140, brightness: 2.4 + // glow: { core: 1.6, inner: 1.4, outer: 0.55, outerRadius: 14.0 } }, // ------------------------------------------------------------------ diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index 9fd47cd..88355ff 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -142,7 +142,13 @@ var FRAG_SRC = [ 'uniform float uMoonFlipU;', 'uniform float uMoonFlipV;', 'uniform float uSunR;', // sun disc angular radius (radians) - 'uniform float uSunDiscGain;', // sun disc/halo brightness gain + 'uniform float uSunDiscGain;', // sun disc/glow brightness gain + 'uniform float uSunGlowOn;', + 'uniform float uSunGlowCore;', + 'uniform float uSunGlowInner;', + 'uniform float uSunGlowOuter;', + 'uniform float uSunGlowOuterRadius;', + 'uniform vec3 uSunGlowColor;', // 3D hash and value noise 'float hash3(vec3 p) {', 'p = fract(p * vec3(0.1031, 0.1030, 0.0973));', @@ -585,11 +591,18 @@ var FRAG_SRC = [ // physical by default) but the surface brightness stays // exactly what it was: the halo profile is normalised to the // disc radius, so the sun is bigger, not brighter. - 'float angN = angS * (0.00465 / uSunR);', - 'float discS = 1.0 - smoothstep(uSunR * 0.86, uSunR, angS);', - 'float haloS = exp(-angN * 55.0) * 0.30 + exp(-angN * 14.0) * 0.12;', - 'vec3 sunCol = mix(uLight, vec3(1.0, 0.92, 0.72), 0.35);', - 'col += sunCol * (discS * 1.15 + haloS) * uSunDiscGain * (1.0 - nightFactor * 0.85);', + 'float angD = angS / max(0.0001, uSunR);', + 'float discS = 1.0 - smoothstep(0.78, 1.0, angD);', + 'float limb = 0.72 + 0.28 * (1.0 - clamp(angD, 0.0, 1.0));', + 'float core = exp(-angD * 2.2) * uSunGlowCore;', + 'float inner = exp(-angD * 0.85) * uSunGlowInner;', + 'float outer = exp(-angD * 0.22) * uSunGlowOuter;', + 'float outerMask = 1.0 - smoothstep(uSunGlowOuterRadius * 0.45, uSunGlowOuterRadius, angD);', + 'float glow = uSunGlowOn * (core + inner + outer * outerMask);', + 'vec3 sunCol = mix(uLight, uSunGlowColor, 0.42);', + 'vec3 glowCol = mix(uSunGlowColor, vec3(1.0, 0.96, 0.82), 0.32);', + 'col += sunCol * discS * limb * 1.35 * uSunDiscGain * (1.0 - nightFactor * 0.85);', + 'col += glowCol * glow * uSunDiscGain * (1.0 - nightFactor * 0.85);', '}', // ---- Moon disc: lunar map + geometric terminator -------------- // The near side always faces the observer, so the map is sampled @@ -1314,6 +1327,12 @@ function init(canvas) { uMoonFrac: uMoonFrac, uMoonEarth: uMoonEarth, uMoonLimb: uMoonLimb, uMoonBright: uMoonBright, uMoonHalo: uMoonHalo, uMoonFlipU: uMoonFlipU, uMoonFlipV: uMoonFlipV, uSunR: uSunR, uSunDiscGain: gl.getUniformLocation(prog, 'uSunDiscGain'), + uSunGlowOn: gl.getUniformLocation(prog, 'uSunGlowOn'), + uSunGlowCore: gl.getUniformLocation(prog, 'uSunGlowCore'), + uSunGlowInner: gl.getUniformLocation(prog, 'uSunGlowInner'), + uSunGlowOuter: gl.getUniformLocation(prog, 'uSunGlowOuter'), + uSunGlowOuterRadius: gl.getUniformLocation(prog, 'uSunGlowOuterRadius'), + uSunGlowColor: gl.getUniformLocation(prog, 'uSunGlowColor'), // terrain program terrain: { prog: terrainProg, @@ -2788,6 +2807,13 @@ var SUN_CFG = (window.CONFIG && window.CONFIG.sun) || {}; var SUN_ANG_R = (typeof SUN_CFG.angularRadius === 'number') ? Math.max(0.00465, SUN_CFG.angularRadius) : 0.00465 * 12; var SUN_DISC_GAIN = (typeof SUN_CFG.brightness === 'number') ? Math.max(0, SUN_CFG.brightness) : 1.0; +var SUN_GLOW_CFG = SUN_CFG.glow || {}; +var SUN_GLOW_ON = SUN_GLOW_CFG.enabled !== false ? 1.0 : 0.0; +var SUN_GLOW_CORE = (typeof SUN_GLOW_CFG.core === 'number') ? Math.max(0, Math.min(4, SUN_GLOW_CFG.core)) : 1.15; +var SUN_GLOW_INNER = (typeof SUN_GLOW_CFG.inner === 'number') ? Math.max(0, Math.min(4, SUN_GLOW_CFG.inner)) : 0.95; +var SUN_GLOW_OUTER = (typeof SUN_GLOW_CFG.outer === 'number') ? Math.max(0, Math.min(4, SUN_GLOW_CFG.outer)) : 0.38; +var SUN_GLOW_OUTER_RADIUS = (typeof SUN_GLOW_CFG.outerRadius === 'number') ? Math.max(1, Math.min(40, SUN_GLOW_CFG.outerRadius)) : 11.0; +var SUN_GLOW_COLOR = Array.isArray(SUN_GLOW_CFG.color) ? SUN_GLOW_CFG.color : [1.00, 0.78, 0.36]; var MOON_TEX_SRC = (typeof window.__moonTex === 'string' && window.__moonTex) ? window.__moonTex : ((typeof MOON_CFG.texture === 'string' && MOON_CFG.texture) ? MOON_CFG.texture : 'vendor/moon.jpg'); @@ -7177,6 +7203,12 @@ window.clouds3dRender = function(target) { gl.uniform1f(s.uMoonFlipV, MOON_FLIP_V); gl.uniform1f(s.uSunR, SUN_ANG_R); gl.uniform1f(s.uSunDiscGain, SUN_DISC_GAIN); + gl.uniform1f(s.uSunGlowOn, SUN_GLOW_ON); + gl.uniform1f(s.uSunGlowCore, SUN_GLOW_CORE); + gl.uniform1f(s.uSunGlowInner, SUN_GLOW_INNER); + gl.uniform1f(s.uSunGlowOuter, SUN_GLOW_OUTER); + gl.uniform1f(s.uSunGlowOuterRadius, SUN_GLOW_OUTER_RADIUS); + gl.uniform3f(s.uSunGlowColor, SUN_GLOW_COLOR[0], SUN_GLOW_COLOR[1], SUN_GLOW_COLOR[2]); // texture path: RA alpha must land at world angle alpha + PI/2 - LST, // which with u = fract(0.5 + (H + uStarLon)/2PI) means uStarLon = LST - 3PI/2 var _sidTex = starSidereal();