atmosphere: replace flickering full-screen haze with stable terrain haze
This commit is contained in:
1 parent
5146d17599
commit
989310ab3b
2 files changed
+71
-4
No files matched your search
@@ -317,7 +317,7 @@ window.CONFIG = {
|
|||||||
rayleighGain: 8.0, // exposure for the physical sky term
|
rayleighGain: 8.0, // exposure for the physical sky term
|
||||||
distanceFog: false, // legacy aerial perspective is off
|
distanceFog: false, // legacy aerial perspective is off
|
||||||
haze: {
|
haze: {
|
||||||
enabled: true,
|
enabled: false, // full-screen haze pass causes horizon/sky flicker
|
||||||
heightKm: 100,
|
heightKm: 100,
|
||||||
scaleHeightKm: 8.5,
|
scaleHeightKm: 8.5,
|
||||||
density: 0.18,
|
density: 0.18,
|
||||||
@@ -325,6 +325,14 @@ window.CONFIG = {
|
|||||||
gain: 1.0,
|
gain: 1.0,
|
||||||
maxAlpha: 0.55
|
maxAlpha: 0.55
|
||||||
},
|
},
|
||||||
|
terrainHaze: {
|
||||||
|
enabled: true,
|
||||||
|
scaleHeightKm: 8.5,
|
||||||
|
density: 0.22,
|
||||||
|
gain: 1.0,
|
||||||
|
maxAlpha: 0.65,
|
||||||
|
color: [0.58, 0.64, 0.72]
|
||||||
|
},
|
||||||
model: {
|
model: {
|
||||||
enabled: false // legacy full atmosphere model remains off
|
enabled: false // legacy full atmosphere model remains off
|
||||||
},
|
},
|
||||||
|
|||||||
Vendored
+62
-3
@@ -688,6 +688,12 @@ var TERRAIN_FRAG_SRC = [
|
|||||||
'uniform vec3 uCamPos;', // world-space camera, for the view direction
|
'uniform vec3 uCamPos;', // world-space camera, for the view direction
|
||||||
'uniform float uEarthRadius;',
|
'uniform float uEarthRadius;',
|
||||||
'uniform float uCurvatureOn;',
|
'uniform float uCurvatureOn;',
|
||||||
|
'uniform float uHazeOn;',
|
||||||
|
'uniform float uHazeDensity;',
|
||||||
|
'uniform float uHazeScaleHeightUnits;',
|
||||||
|
'uniform float uHazeGain;',
|
||||||
|
'uniform float uHazeMaxAlpha;',
|
||||||
|
'uniform vec3 uHazeColor;',
|
||||||
'uniform float uEdgeFadeTiles;',
|
'uniform float uEdgeFadeTiles;',
|
||||||
'uniform vec3 uWireColor;', // non-zero -> debug wireframe overlay (flat colour)
|
'uniform vec3 uWireColor;', // non-zero -> debug wireframe overlay (flat colour)
|
||||||
'varying vec3 vNormal;',
|
'varying vec3 vNormal;',
|
||||||
@@ -697,6 +703,21 @@ var TERRAIN_FRAG_SRC = [
|
|||||||
'varying vec3 vWorld;',
|
'varying vec3 vWorld;',
|
||||||
'varying vec3 vColor;',
|
'varying vec3 vColor;',
|
||||||
CLOUD_SAMPLER_GLSL,
|
CLOUD_SAMPLER_GLSL,
|
||||||
|
'float terrainHazeColumn(vec3 world) {',
|
||||||
|
'float dist = length(world - uCamPos);',
|
||||||
|
'if (dist <= 0.0) return 0.0;',
|
||||||
|
'if (uCurvatureOn < 0.5) return dist;',
|
||||||
|
'float R = max(1.0, uEarthRadius);',
|
||||||
|
'float Hs = max(0.05, uHazeScaleHeightUnits);',
|
||||||
|
'vec3 C = vec3(uCamPos.x, -R, uCamPos.z);',
|
||||||
|
'float column = 0.0;',
|
||||||
|
'for (int i = 0; i < 8; i++) {',
|
||||||
|
'vec3 p = mix(uCamPos, world, (float(i) + 0.5) / 8.0);',
|
||||||
|
'float alt = max(0.0, length(p - C) - R);',
|
||||||
|
'column += exp(-alt / Hs) * dist / 8.0 / Hs;',
|
||||||
|
'}',
|
||||||
|
'return column;',
|
||||||
|
'}',
|
||||||
'void main() {',
|
'void main() {',
|
||||||
'vec2 gUv = vUV;',
|
'vec2 gUv = vUV;',
|
||||||
// Edge fade: beyond the canvas the texture is clamped to the
|
// Edge fade: beyond the canvas the texture is clamped to the
|
||||||
@@ -784,12 +805,19 @@ var TERRAIN_FRAG_SRC = [
|
|||||||
// veil but into the airlight itself - blue-biased (Rayleigh,
|
// veil but into the airlight itself - blue-biased (Rayleigh,
|
||||||
// 1/lambda^4) and brighter towards the sun through the (1+cos^2)/2
|
// 1/lambda^4) and brighter towards the sun through the (1+cos^2)/2
|
||||||
// phase function.
|
// phase function.
|
||||||
'float tau = uAirDensity * dist * (0.75 + 0.25 * smoothstep(0.4, 0.0, vY));',
|
'float hazeTau = 0.0;',
|
||||||
'float trans = exp(-tau);',
|
'if (uHazeOn > 0.5) {',
|
||||||
|
'hazeTau = uHazeDensity * terrainHazeColumn(vWorld);',
|
||||||
|
'} else {',
|
||||||
|
'hazeTau = uAirDensity * dist * (0.75 + 0.25 * smoothstep(0.4, 0.0, vY));',
|
||||||
|
'}',
|
||||||
|
'float trans = exp(-hazeTau);',
|
||||||
'vec3 vd = normalize(vWorld - uCamPos);',
|
'vec3 vd = normalize(vWorld - uCamPos);',
|
||||||
'float cosT = dot(vd, uSunDir);',
|
'float cosT = dot(vd, uSunDir);',
|
||||||
'float rphase = 0.5 + 0.5 * cosT * cosT;',
|
'float rphase = 0.5 + 0.5 * cosT * cosT;',
|
||||||
'col = col * trans + uAirColor * rphase * (1.0 - trans);',
|
'float hazeAlpha = clamp((1.0 - trans) * uHazeGain, 0.0, uHazeMaxAlpha);',
|
||||||
|
'vec3 hazeCol = mix(uHazeColor, uAirColor, 0.25) * (0.75 + 0.25 * rphase);',
|
||||||
|
'col = mix(col, hazeCol, hazeAlpha);',
|
||||||
// Edge fade to the same horizon colour
|
// Edge fade to the same horizon colour
|
||||||
'col = mix(horizonCol, col, edgeFade);',
|
'col = mix(horizonCol, col, edgeFade);',
|
||||||
// Wireframe overlay: when CONFIG.terrain.wireframe is set the
|
// Wireframe overlay: when CONFIG.terrain.wireframe is set the
|
||||||
@@ -944,6 +972,12 @@ function init(canvas) {
|
|||||||
var terrainUEarthRadius = terrainProg ? gl.getUniformLocation(terrainProg, 'uEarthRadius') : null;
|
var terrainUEarthRadius = terrainProg ? gl.getUniformLocation(terrainProg, 'uEarthRadius') : null;
|
||||||
var terrainUCurvatureOn = terrainProg ? gl.getUniformLocation(terrainProg, 'uCurvatureOn') : null;
|
var terrainUCurvatureOn = terrainProg ? gl.getUniformLocation(terrainProg, 'uCurvatureOn') : null;
|
||||||
var terrainUedgeFade = terrainProg ? gl.getUniformLocation(terrainProg, 'uEdgeFadeTiles') : null;
|
var terrainUedgeFade = terrainProg ? gl.getUniformLocation(terrainProg, 'uEdgeFadeTiles') : null;
|
||||||
|
var terrainUHazeOn = terrainProg ? gl.getUniformLocation(terrainProg, 'uHazeOn') : null;
|
||||||
|
var terrainUHazeDensity = terrainProg ? gl.getUniformLocation(terrainProg, 'uHazeDensity') : null;
|
||||||
|
var terrainUHazeScale = terrainProg ? gl.getUniformLocation(terrainProg, 'uHazeScaleHeightUnits') : null;
|
||||||
|
var terrainUHazeGain = terrainProg ? gl.getUniformLocation(terrainProg, 'uHazeGain') : null;
|
||||||
|
var terrainUHazeMaxAlpha = terrainProg ? gl.getUniformLocation(terrainProg, 'uHazeMaxAlpha') : null;
|
||||||
|
var terrainUHazeColor = terrainProg ? gl.getUniformLocation(terrainProg, 'uHazeColor') : null;
|
||||||
var terrainUstarAmb = terrainProg ? gl.getUniformLocation(terrainProg, 'uStarAmb') : null;
|
var terrainUstarAmb = terrainProg ? gl.getUniformLocation(terrainProg, 'uStarAmb') : null;
|
||||||
var terrainUtime = terrainProg ? gl.getUniformLocation(terrainProg, 'uTime') : null;
|
var terrainUtime = terrainProg ? gl.getUniformLocation(terrainProg, 'uTime') : null;
|
||||||
var terrainUcloudbot = terrainProg ? gl.getUniformLocation(terrainProg, 'uCloudBot') : null;
|
var terrainUcloudbot = terrainProg ? gl.getUniformLocation(terrainProg, 'uCloudBot') : null;
|
||||||
@@ -1021,6 +1055,9 @@ function init(canvas) {
|
|||||||
uCamPos: terrainUcampos,
|
uCamPos: terrainUcampos,
|
||||||
uEarthRadius: terrainUEarthRadius, uCurvatureOn: terrainUCurvatureOn,
|
uEarthRadius: terrainUEarthRadius, uCurvatureOn: terrainUCurvatureOn,
|
||||||
uEdgeFadeTiles: terrainUedgeFade,
|
uEdgeFadeTiles: terrainUedgeFade,
|
||||||
|
uHazeOn: terrainUHazeOn, uHazeDensity: terrainUHazeDensity,
|
||||||
|
uHazeScaleHeightUnits: terrainUHazeScale, uHazeGain: terrainUHazeGain,
|
||||||
|
uHazeMaxAlpha: terrainUHazeMaxAlpha, uHazeColor: terrainUHazeColor,
|
||||||
uStarAmb: terrainUstarAmb,
|
uStarAmb: terrainUstarAmb,
|
||||||
uTime: terrainUtime, uCloudBot: terrainUcloudbot,
|
uTime: terrainUtime, uCloudBot: terrainUcloudbot,
|
||||||
uCloudTop: terrainUcloudtop, uDensity: terrainUdensity,
|
uCloudTop: terrainUcloudtop, uDensity: terrainUdensity,
|
||||||
@@ -2463,6 +2500,22 @@ var ATMO_MODEL_MAX_ALPHA = (typeof HAZE_CFG.maxAlpha === 'number')
|
|||||||
? Math.max(0.05, Math.min(1.0, HAZE_CFG.maxAlpha))
|
? Math.max(0.05, Math.min(1.0, HAZE_CFG.maxAlpha))
|
||||||
: ((typeof ATMO_MODEL.maxAlpha === 'number')
|
: ((typeof ATMO_MODEL.maxAlpha === 'number')
|
||||||
? Math.max(0.05, Math.min(1.0, ATMO_MODEL.maxAlpha)) : 0.55);
|
? Math.max(0.05, Math.min(1.0, ATMO_MODEL.maxAlpha)) : 0.55);
|
||||||
|
var TERRAIN_HAZE_CFG = ATMO.terrainHaze || {};
|
||||||
|
var TERRAIN_HAZE_ON = TERRAIN_HAZE_CFG.enabled !== false;
|
||||||
|
var TERRAIN_HAZE_SCALE_HEIGHT_KM = (typeof TERRAIN_HAZE_CFG.scaleHeightKm === 'number')
|
||||||
|
? Math.max(1.0, Math.min(30.0, TERRAIN_HAZE_CFG.scaleHeightKm)) : 8.5;
|
||||||
|
var TERRAIN_HAZE_SCALE_HEIGHT_UNITS = TERRAIN_HAZE_SCALE_HEIGHT_KM / KM_PER_TILE;
|
||||||
|
var TERRAIN_HAZE_DENSITY = (typeof TERRAIN_HAZE_CFG.density === 'number')
|
||||||
|
? Math.max(0.01, Math.min(5.0, TERRAIN_HAZE_CFG.density)) : 0.22;
|
||||||
|
var TERRAIN_HAZE_GAIN = (typeof TERRAIN_HAZE_CFG.gain === 'number')
|
||||||
|
? Math.max(0.1, Math.min(5.0, TERRAIN_HAZE_CFG.gain)) : 1.0;
|
||||||
|
var TERRAIN_HAZE_MAX_ALPHA = (typeof TERRAIN_HAZE_CFG.maxAlpha === 'number')
|
||||||
|
? Math.max(0.05, Math.min(1.0, TERRAIN_HAZE_CFG.maxAlpha)) : 0.65;
|
||||||
|
var TERRAIN_HAZE_COLOR = new Float32Array(
|
||||||
|
Array.isArray(TERRAIN_HAZE_CFG.color) && TERRAIN_HAZE_CFG.color.length >= 3
|
||||||
|
? [TERRAIN_HAZE_CFG.color[0], TERRAIN_HAZE_CFG.color[1], TERRAIN_HAZE_CFG.color[2]]
|
||||||
|
: [0.58, 0.64, 0.72]
|
||||||
|
);
|
||||||
var CURV_CFG = (window.CONFIG && window.CONFIG.curvature) || {};
|
var CURV_CFG = (window.CONFIG && window.CONFIG.curvature) || {};
|
||||||
var CURVATURE_ON = CURV_CFG.enabled !== false;
|
var CURVATURE_ON = CURV_CFG.enabled !== false;
|
||||||
var CURV_EXAG = (typeof CURV_CFG.exaggeration === 'number')
|
var CURV_EXAG = (typeof CURV_CFG.exaggeration === 'number')
|
||||||
@@ -5845,6 +5898,12 @@ window.clouds3dRender = function(target) {
|
|||||||
gl.uniform1f(terr.uEarthRadius, EARTH_RADIUS_UNITS);
|
gl.uniform1f(terr.uEarthRadius, EARTH_RADIUS_UNITS);
|
||||||
gl.uniform1f(terr.uCurvatureOn, CURVATURE_ON ? 1.0 : 0.0);
|
gl.uniform1f(terr.uCurvatureOn, CURVATURE_ON ? 1.0 : 0.0);
|
||||||
gl.uniform1f(terr.uEdgeFadeTiles, EDGE_FADE_TILES);
|
gl.uniform1f(terr.uEdgeFadeTiles, EDGE_FADE_TILES);
|
||||||
|
gl.uniform1f(terr.uHazeOn, TERRAIN_HAZE_ON ? 1.0 : 0.0);
|
||||||
|
gl.uniform1f(terr.uHazeDensity, TERRAIN_HAZE_DENSITY);
|
||||||
|
gl.uniform1f(terr.uHazeScaleHeightUnits, TERRAIN_HAZE_SCALE_HEIGHT_UNITS);
|
||||||
|
gl.uniform1f(terr.uHazeGain, TERRAIN_HAZE_GAIN);
|
||||||
|
gl.uniform1f(terr.uHazeMaxAlpha, TERRAIN_HAZE_MAX_ALPHA);
|
||||||
|
gl.uniform3f(terr.uHazeColor, TERRAIN_HAZE_COLOR[0], TERRAIN_HAZE_COLOR[1], TERRAIN_HAZE_COLOR[2]);
|
||||||
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, terr.vbo);
|
gl.bindBuffer(gl.ARRAY_BUFFER, terr.vbo);
|
||||||
var STRIDE = 11 * 4; // 11 floats per vertex
|
var STRIDE = 11 * 4; // 11 floats per vertex
|
||||||
|
|||||||
Reference in new issue
Block a user