atmosphere: add stable air haze behind terrain
This commit is contained in:
1 parent
989310ab3b
commit
a33e6ddcfc
2 files changed
+100
-1
No files matched your search
@@ -333,6 +333,14 @@ window.CONFIG = {
|
||||
maxAlpha: 0.65,
|
||||
color: [0.58, 0.64, 0.72]
|
||||
},
|
||||
airHaze: {
|
||||
enabled: true,
|
||||
scaleHeightKm: 8.5,
|
||||
density: 0.16,
|
||||
gain: 1.0,
|
||||
maxAlpha: 0.45,
|
||||
color: [0.58, 0.64, 0.72]
|
||||
},
|
||||
model: {
|
||||
enabled: false // legacy full atmosphere model remains off
|
||||
},
|
||||
|
||||
Vendored
+92
-1
@@ -110,6 +110,12 @@ var FRAG_SRC = [
|
||||
'uniform float uSunAirMass;', // relative air mass of the sun beam
|
||||
'uniform float uRayleighGain;',
|
||||
'uniform float uPhysicalSkyOn;',
|
||||
'uniform float uAirHazeOn;',
|
||||
'uniform float uAirHazeDensity;',
|
||||
'uniform float uAirHazeScaleHeightUnits;',
|
||||
'uniform float uAirHazeGain;',
|
||||
'uniform float uAirHazeMaxAlpha;',
|
||||
'uniform vec3 uAirHazeColor;',
|
||||
'uniform vec3 uCloudAlbedo;', // theme-tinted but brightness-normalised
|
||||
'uniform float uAirDensity;', // slant optical depth per world unit
|
||||
'uniform float uCloudHaze;', // clouds sit above most of the haze: much weaker
|
||||
@@ -303,6 +309,51 @@ var FRAG_SRC = [
|
||||
'}',
|
||||
'return uRayleighBeta * column;',
|
||||
'}',
|
||||
'float airHazeColumn(vec3 rd) {',
|
||||
'if (uCurvatureOn < 0.5) {',
|
||||
'float viewY = max(rd.y, 0.0);',
|
||||
'float mView = (viewY > 0.02) ? min(38.0, 1.0 / viewY) : 38.0;',
|
||||
'return mView;',
|
||||
'}',
|
||||
'float R = max(1.0, uEarthRadius);',
|
||||
'float H = max(1.0, uAtmoHeightUnits);',
|
||||
'float Hs = max(0.05, uAirHazeScaleHeightUnits);',
|
||||
'vec3 C = vec3(uCamPos.x, -R, uCamPos.z);',
|
||||
'vec3 oc = uCamPos - C;',
|
||||
'float b = dot(oc, rd);',
|
||||
'float rOut = R + H;',
|
||||
'float cOut = dot(oc, oc) - rOut * rOut;',
|
||||
'float tStart = 0.0;',
|
||||
'float tEnd = 100.0;',
|
||||
'float discOut = b * b - cOut;',
|
||||
'if (discOut > 0.0) {',
|
||||
'float sq = sqrt(discOut);',
|
||||
'float t1 = -b - sq;',
|
||||
'float t2 = -b + sq;',
|
||||
'if (cOut > 0.0) tStart = max(0.0, t1);',
|
||||
'tEnd = max(0.0, t2);',
|
||||
'}',
|
||||
'float cIn = dot(oc, oc) - R * R;',
|
||||
'float discIn = b * b - cIn;',
|
||||
'if (discIn > 0.0) {',
|
||||
'float sq = sqrt(discIn);',
|
||||
'float t1 = -b - sq;',
|
||||
'float t2 = -b + sq;',
|
||||
'if (t1 > 0.0) tEnd = min(tEnd, t1);',
|
||||
'else if (t2 > 0.0) tEnd = min(tEnd, t2);',
|
||||
'}',
|
||||
'if (tEnd <= tStart) return 0.0;',
|
||||
'float step = (tEnd - tStart) / 16.0;',
|
||||
'float t = tStart + step * 0.5;',
|
||||
'float column = 0.0;',
|
||||
'for (int i = 0; i < 16; i++) {',
|
||||
'vec3 p = uCamPos + rd * t;',
|
||||
'float alt = max(0.0, length(p - C) - R);',
|
||||
'column += exp(-alt / Hs) * step / Hs;',
|
||||
't += step;',
|
||||
'}',
|
||||
'return column;',
|
||||
'}',
|
||||
// Two modes driven by uMode:
|
||||
// 0 = SKY: full-screen pass that paints the sky gradient and
|
||||
// stars into the framebuffer (opaque, alpha = 1).
|
||||
@@ -402,6 +453,12 @@ var FRAG_SRC = [
|
||||
'vec3 phys = (single + multi + ambient) * uRayleighGain;',
|
||||
'col = mix(col, phys, 0.82);',
|
||||
'}',
|
||||
'if (uAirHazeOn > 0.5) {',
|
||||
'float hazeColumn = airHazeColumn(rd);',
|
||||
'float hazeTau = uAirHazeDensity * hazeColumn;',
|
||||
'float hazeAlpha = clamp((1.0 - exp(-hazeTau)) * uAirHazeGain, 0.0, uAirHazeMaxAlpha);',
|
||||
'col = mix(col, uAirHazeColor, hazeAlpha);',
|
||||
'}',
|
||||
'float nightFactor = 1.0 - smoothstep(-0.15, 0.05, uSunAlt);',
|
||||
'float skyMask = smoothstep(-0.20, 0.40, rd.y);',
|
||||
// Stars must not sit on the moon: the disc is opaque, so every
|
||||
@@ -924,6 +981,12 @@ function init(canvas) {
|
||||
var uSunAirMass = gl.getUniformLocation(prog, 'uSunAirMass');
|
||||
var uRayleighGain = gl.getUniformLocation(prog, 'uRayleighGain');
|
||||
var uPhysicalSkyOn = gl.getUniformLocation(prog, 'uPhysicalSkyOn');
|
||||
var uAirHazeOn = gl.getUniformLocation(prog, 'uAirHazeOn');
|
||||
var uAirHazeDensity = gl.getUniformLocation(prog, 'uAirHazeDensity');
|
||||
var uAirHazeScaleHeightUnits = gl.getUniformLocation(prog, 'uAirHazeScaleHeightUnits');
|
||||
var uAirHazeGain = gl.getUniformLocation(prog, 'uAirHazeGain');
|
||||
var uAirHazeMaxAlpha = gl.getUniformLocation(prog, 'uAirHazeMaxAlpha');
|
||||
var uAirHazeColor = gl.getUniformLocation(prog, 'uAirHazeColor');
|
||||
var uCloudAlbedo = gl.getUniformLocation(prog, 'uCloudAlbedo');
|
||||
var uAirDensity = gl.getUniformLocation(prog, 'uAirDensity');
|
||||
var uCloudHaze = gl.getUniformLocation(prog, 'uCloudHaze');
|
||||
@@ -1029,7 +1092,11 @@ function init(canvas) {
|
||||
uMoonInt: uMoonInt, uSkyAmb: uSkyAmb, uStarAmb: uStarAmb,
|
||||
uPhysical: uPhysical, uAirColor: uAirColor,
|
||||
uRayleighBeta: uRayleighBeta, uSunAirMass: uSunAirMass,
|
||||
uRayleighGain: uRayleighGain, uPhysicalSkyOn: uPhysicalSkyOn, uCloudAlbedo: uCloudAlbedo,
|
||||
uRayleighGain: uRayleighGain, uPhysicalSkyOn: uPhysicalSkyOn,
|
||||
uAirHazeOn: uAirHazeOn, uAirHazeDensity: uAirHazeDensity,
|
||||
uAirHazeScaleHeightUnits: uAirHazeScaleHeightUnits,
|
||||
uAirHazeGain: uAirHazeGain, uAirHazeMaxAlpha: uAirHazeMaxAlpha,
|
||||
uAirHazeColor: uAirHazeColor, uCloudAlbedo: uCloudAlbedo,
|
||||
uAirDensity: uAirDensity, uCloudHaze: uCloudHaze,
|
||||
uSkyTex: uSkyTex, uSkyOn: uSkyOn, uStarLon: uStarLon, uPole: uPole,
|
||||
uMoonTex: uMoonTex, uMoonTexOn: uMoonTexOn, uMoonR: uMoonR,
|
||||
@@ -2516,6 +2583,24 @@ var TERRAIN_HAZE_COLOR = new Float32Array(
|
||||
? [TERRAIN_HAZE_CFG.color[0], TERRAIN_HAZE_CFG.color[1], TERRAIN_HAZE_CFG.color[2]]
|
||||
: [0.58, 0.64, 0.72]
|
||||
);
|
||||
var AIR_HAZE_CFG = ATMO.airHaze || TERRAIN_HAZE_CFG || {};
|
||||
var AIR_HAZE_ON = (typeof AIR_HAZE_CFG.enabled === 'boolean')
|
||||
? AIR_HAZE_CFG.enabled
|
||||
: (TERRAIN_HAZE_ON && AIR_HAZE_CFG.enabled !== false);
|
||||
var AIR_HAZE_SCALE_HEIGHT_KM = (typeof AIR_HAZE_CFG.scaleHeightKm === 'number')
|
||||
? Math.max(1.0, Math.min(30.0, AIR_HAZE_CFG.scaleHeightKm)) : 8.5;
|
||||
var AIR_HAZE_SCALE_HEIGHT_UNITS = AIR_HAZE_SCALE_HEIGHT_KM / KM_PER_TILE;
|
||||
var AIR_HAZE_DENSITY = (typeof AIR_HAZE_CFG.density === 'number')
|
||||
? Math.max(0.01, Math.min(5.0, AIR_HAZE_CFG.density)) : 0.16;
|
||||
var AIR_HAZE_GAIN = (typeof AIR_HAZE_CFG.gain === 'number')
|
||||
? Math.max(0.1, Math.min(5.0, AIR_HAZE_CFG.gain)) : 1.0;
|
||||
var AIR_HAZE_MAX_ALPHA = (typeof AIR_HAZE_CFG.maxAlpha === 'number')
|
||||
? Math.max(0.05, Math.min(1.0, AIR_HAZE_CFG.maxAlpha)) : 0.45;
|
||||
var AIR_HAZE_COLOR = new Float32Array(
|
||||
Array.isArray(AIR_HAZE_CFG.color) && AIR_HAZE_CFG.color.length >= 3
|
||||
? [AIR_HAZE_CFG.color[0], AIR_HAZE_CFG.color[1], AIR_HAZE_CFG.color[2]]
|
||||
: [0.58, 0.64, 0.72]
|
||||
);
|
||||
var CURV_CFG = (window.CONFIG && window.CONFIG.curvature) || {};
|
||||
var CURVATURE_ON = CURV_CFG.enabled !== false;
|
||||
var CURV_EXAG = (typeof CURV_CFG.exaggeration === 'number')
|
||||
@@ -5608,6 +5693,12 @@ window.clouds3dRender = function(target) {
|
||||
gl.uniform1f(s.uSunAirMass, airMass(Math.max(sunAlt, 0.0)));
|
||||
gl.uniform1f(s.uRayleighGain, ATMO_RAYLEIGH_GAIN);
|
||||
gl.uniform1f(s.uPhysicalSkyOn, ATMO_PHYSICAL_SKY ? 1.0 : 0.0);
|
||||
gl.uniform1f(s.uAirHazeOn, AIR_HAZE_ON ? 1.0 : 0.0);
|
||||
gl.uniform1f(s.uAirHazeDensity, AIR_HAZE_DENSITY);
|
||||
gl.uniform1f(s.uAirHazeScaleHeightUnits, AIR_HAZE_SCALE_HEIGHT_UNITS);
|
||||
gl.uniform1f(s.uAirHazeGain, AIR_HAZE_GAIN);
|
||||
gl.uniform1f(s.uAirHazeMaxAlpha, AIR_HAZE_MAX_ALPHA);
|
||||
gl.uniform3f(s.uAirHazeColor, AIR_HAZE_COLOR[0], AIR_HAZE_COLOR[1], AIR_HAZE_COLOR[2]);
|
||||
gl.uniform3f(s.uSunColor, _beam[0], _beam[1], _beam[2]);
|
||||
gl.uniform1f(s.uSunInt, _beamL);
|
||||
gl.uniform3f(s.uMoonColor, _mBeam[0], _mBeam[1], _mBeam[2]);
|
||||
|
||||
Reference in new issue
Block a user