atmosphere: add initial volumetric atmosphere shell
This commit is contained in:
1 parent
1f925c6f68
commit
b9094ebd8b
2 files changed
+113
-1
No files matched your search
Vendored
+104
-1
@@ -85,7 +85,15 @@ var FRAG_SRC = [
|
||||
'uniform float uSkyOn;', // 0 until the star texture is built
|
||||
'uniform float uStarLon;', // sidereal rotation offset (radians)
|
||||
'uniform vec3 uPole;', // north celestial pole in world coords
|
||||
'uniform int uMode;', // 0 = sky+stars, 1 = clouds (transparent over mesh)
|
||||
'uniform int uMode;', // 0 = sky+stars, 1 = clouds, 2 = atmosphere shell
|
||||
'uniform float uAtmoModelOn;',
|
||||
'uniform float uAtmoHeightUnits;',
|
||||
'uniform float uAtmoScaleHeightUnits;',
|
||||
'uniform float uAtmoDensity;',
|
||||
'uniform float uAtmoGrayTau;',
|
||||
'uniform float uAtmoGain;',
|
||||
'uniform vec3 uAtmoBlueColor;',
|
||||
'uniform vec3 uAtmoGrayColor;',
|
||||
'uniform vec3 uSunColor;', // direct beam after atmospheric extinction
|
||||
'uniform float uSunInt;',
|
||||
'uniform vec3 uMoonColor;',
|
||||
@@ -227,6 +235,64 @@ var FRAG_SRC = [
|
||||
'vec3 ro = nearH.xyz / nearH.w;',
|
||||
'vec3 rd = normalize(farH.xyz / farH.w - ro);',
|
||||
|
||||
'if (uMode == 2) {',
|
||||
'if (uAtmoModelOn < 0.5) { gl_FragColor = vec4(0.0); return; }',
|
||||
'float R = max(1.0, uEarthRadius);',
|
||||
'float H = max(0.1, uAtmoHeightUnits);',
|
||||
'float Hs = max(0.01, uAtmoScaleHeightUnits);',
|
||||
'vec3 C = vec3(ro.x, -R, ro.z);',
|
||||
'vec3 oc = ro - C;',
|
||||
'float b = dot(oc, rd);',
|
||||
'float rOut = R + H;',
|
||||
'float cOut = dot(oc, oc) - rOut * rOut;',
|
||||
'float discOut = b * b - cOut;',
|
||||
'float tStart = 0.0;',
|
||||
'float tEnd = 100.0;',
|
||||
'if (discOut > 0.0) {',
|
||||
'float sq = sqrt(discOut);',
|
||||
'float t1 = -b - sq;',
|
||||
'float t2 = -b + sq;',
|
||||
'if (dot(oc, oc) > rOut * rOut) tStart = max(0.0, t1);',
|
||||
'tEnd = max(0.0, t2);',
|
||||
'}',
|
||||
'float cIn = dot(oc, oc) - R * R;',
|
||||
'float discIn = b * b - cIn;',
|
||||
'float tInner = 100000.0;',
|
||||
'if (discIn > 0.0) {',
|
||||
'float sq = sqrt(discIn);',
|
||||
'float t1 = -b - sq;',
|
||||
'float t2 = -b + sq;',
|
||||
'if (t1 > 0.0) tInner = t1;',
|
||||
'else if (t2 > 0.0) tInner = t2;',
|
||||
'}',
|
||||
'if (tInner < 100000.0) tEnd = min(tEnd, tInner);',
|
||||
'if (tEnd <= tStart) { gl_FragColor = vec4(0.0); return; }',
|
||||
'float step = (tEnd - tStart) / 32.0;',
|
||||
'float t = tStart + step * 0.5;',
|
||||
'float tau = 0.0;',
|
||||
'vec3 scatter = vec3(0.0);',
|
||||
'float cosTA = dot(rd, uSunDir);',
|
||||
'float cosTM = dot(rd, uMoonDir);',
|
||||
'float sunPhase = 0.25 + 0.75 * pow(max(0.0, cosTA), 2.0);',
|
||||
'float moonPhase = 0.25 + 0.75 * pow(max(0.0, cosTM), 2.0);',
|
||||
'for (int i = 0; i < 32; i++) {',
|
||||
'vec3 p = ro + rd * t;',
|
||||
'float alt = max(0.0, length(p - C) - R);',
|
||||
'float dens = exp(-alt / Hs);',
|
||||
'float dtau = uAtmoDensity * dens * step;',
|
||||
'float transBefore = exp(-tau);',
|
||||
'float grayMix = clamp(tau / max(0.01, uAtmoGrayTau), 0.0, 1.0);',
|
||||
'vec3 atmoCol = mix(uAtmoBlueColor, uAtmoGrayColor, grayMix);',
|
||||
'vec3 light = uSunColor * uSunInt * sunPhase + uMoonColor * uMoonInt * moonPhase * 2.0 + max(vec3(uSkyAmb), uStarAmb * vec3(0.7, 0.85, 1.0)) * 0.65;',
|
||||
'scatter += atmoCol * light * dtau * transBefore;',
|
||||
'tau += dtau;',
|
||||
't += step;',
|
||||
'}',
|
||||
'float alpha = clamp(1.0 - exp(-tau), 0.0, 1.0);',
|
||||
'vec3 col = scatter / max(alpha, 1e-4) * uAtmoGain;',
|
||||
'gl_FragColor = vec4(col, alpha);',
|
||||
'return;',
|
||||
'}',
|
||||
'if (uMode == 0) {',
|
||||
// skyT floor at 0.5: at and below the horizon the sky keeps
|
||||
// the exact horizon colour - the same value the terrain's
|
||||
@@ -853,6 +919,11 @@ function init(canvas) {
|
||||
uCloudTop: uCloudTop, uCloudBot: uCloudBot,
|
||||
uElev: uElev, uElevOn: uElevOn, uElevScale: uElevScale,
|
||||
uSunDir: uSunDir, uMoonDir: uMoonDir, uMode: uMode,
|
||||
uAtmoModelOn: uAtmoModelOn, uAtmoHeightUnits: uAtmoHeightUnits,
|
||||
uAtmoScaleHeightUnits: uAtmoScaleHeightUnits, uAtmoDensity: uAtmoDensity,
|
||||
uAtmoGrayTau: uAtmoGrayTau, uAtmoGain: uAtmoGain,
|
||||
uEarthRadius: uEarthRadius,
|
||||
uAtmoBlueColor: uAtmoBlueColor, uAtmoGrayColor: uAtmoGrayColor,
|
||||
uSunColor: uSunColor, uSunInt: uSunInt, uMoonColor: uMoonColor,
|
||||
uMoonInt: uMoonInt, uSkyAmb: uSkyAmb, uStarAmb: uStarAmb,
|
||||
uPhysical: uPhysical, uAirColor: uAirColor, uCloudAlbedo: uCloudAlbedo,
|
||||
@@ -2041,6 +2112,23 @@ var RAYLEIGH = [0.192, 0.451, 1.0];
|
||||
var ATMO_AIR_GAIN = (typeof ATMO.airGain === 'number') ? Math.max(0.05, ATMO.airGain) : 0.55;
|
||||
var ATMO_HAZE_RESIDUAL = (typeof ATMO.hazeResidual === 'number')
|
||||
? Math.max(0.02, Math.min(0.95, ATMO.hazeResidual)) : 0.30;
|
||||
var ATMO_DISTANCE_FOG = ATMO.distanceFog !== false;
|
||||
var ATMO_MODEL = ATMO.model || {};
|
||||
var ATMO_MODEL_ON = ATMO_MODEL.enabled !== false;
|
||||
var ATMO_MODEL_HEIGHT_KM = (typeof ATMO_MODEL.heightKm === 'number')
|
||||
? Math.max(1.0, Math.min(80.0, ATMO_MODEL.heightKm)) : 35.0;
|
||||
var ATMO_MODEL_HEIGHT_UNITS = ATMO_MODEL_HEIGHT_KM / KM_PER_TILE;
|
||||
var ATMO_MODEL_SCALE_HEIGHT_KM = (typeof ATMO_MODEL.scaleHeightKm === 'number')
|
||||
? Math.max(1.0, Math.min(30.0, ATMO_MODEL.scaleHeightKm)) : 8.5;
|
||||
var ATMO_MODEL_SCALE_HEIGHT_UNITS = ATMO_MODEL_SCALE_HEIGHT_KM / KM_PER_TILE;
|
||||
var ATMO_MODEL_DENSITY = (typeof ATMO_MODEL.density === 'number')
|
||||
? Math.max(0.01, Math.min(5.0, ATMO_MODEL.density)) : 0.12;
|
||||
var ATMO_MODEL_GRAY_TAU = (typeof ATMO_MODEL.grayTau === 'number')
|
||||
? Math.max(0.1, Math.min(10.0, ATMO_MODEL.grayTau)) : 1.5;
|
||||
var ATMO_MODEL_GAIN = (typeof ATMO_MODEL.gain === 'number')
|
||||
? Math.max(0.1, Math.min(5.0, ATMO_MODEL.gain)) : 2.0;
|
||||
var ATMO_MODEL_BLUE_COLOR = new Float32Array([0.22, 0.42, 0.95]);
|
||||
var ATMO_MODEL_GRAY_COLOR = new Float32Array([0.72, 0.76, 0.82]);
|
||||
// Integrated starlight + airglow. Physically this is about a millionth of
|
||||
// daylight, so it is a stylised floor (CONFIG.atmosphere.starGain) that
|
||||
// keeps clouds, contrails and the ground from going fully black on a
|
||||
@@ -5112,6 +5200,15 @@ window.clouds3dRender = function(target) {
|
||||
gl.uniform3f(s.uMoonColor, _mBeam[0], _mBeam[1], _mBeam[2]);
|
||||
gl.uniform1f(s.uMoonInt, _moonI);
|
||||
gl.uniform1f(s.uSkyAmb, _amb * ATMO_SKY_GAIN);
|
||||
gl.uniform1f(s.uAtmoModelOn, ATMO_MODEL_ON ? 1.0 : 0.0);
|
||||
gl.uniform1f(s.uAtmoHeightUnits, ATMO_MODEL_HEIGHT_UNITS);
|
||||
gl.uniform1f(s.uAtmoScaleHeightUnits, ATMO_MODEL_SCALE_HEIGHT_UNITS);
|
||||
gl.uniform1f(s.uAtmoDensity, ATMO_MODEL_DENSITY);
|
||||
gl.uniform1f(s.uAtmoGrayTau, ATMO_MODEL_GRAY_TAU);
|
||||
gl.uniform1f(s.uAtmoGain, ATMO_MODEL_GAIN);
|
||||
gl.uniform1f(s.uEarthRadius, EARTH_RADIUS_UNITS);
|
||||
gl.uniform3fv(s.uAtmoBlueColor, ATMO_MODEL_BLUE_COLOR);
|
||||
gl.uniform3fv(s.uAtmoGrayColor, ATMO_MODEL_GRAY_COLOR);
|
||||
gl.uniform1f(s.uStarAmb, _star);
|
||||
// Theme cloud hue kept, brightness normalised: the light model, not the
|
||||
// palette, decides how bright a cloud is.
|
||||
@@ -5937,6 +6034,12 @@ window.clouds3dRender = function(target) {
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
gl.uniform1i(s.uMode, 1);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
||||
|
||||
if (ATMO_MODEL_ON) {
|
||||
gl.uniform1i(s.uMode, 2);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
||||
}
|
||||
|
||||
// Restore default state for the next frame.
|
||||
gl.disable(gl.BLEND);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
|
||||
Reference in new issue
Block a user