curvature: bend terrain vertices to a spherical Earth

This commit is contained in:
Richard Zink committed 2026-10-12 14:04:29 +02:00
1 parent f2a3a2172d
commit e78c6e86b6
1 file changed
+30 -6
+30 -6
View File
@@ -530,17 +530,30 @@ var TERRAIN_VERT_SRC = [
'attribute vec2 aUV;', 'attribute vec2 aUV;',
'uniform mat4 uView;', 'uniform mat4 uView;',
'uniform mat4 uProj;', 'uniform mat4 uProj;',
'uniform vec3 uCamPos;',
'uniform float uEarthRadius;',
'uniform float uCurvatureOn;',
'varying vec3 vNormal;', 'varying vec3 vNormal;',
'varying vec2 vUV;', 'varying vec2 vUV;',
'varying float vY;', 'varying float vY;',
'varying vec3 vViewPos;', 'varying vec3 vViewPos;',
'varying vec3 vWorld;', 'varying vec3 vWorld;',
'void main() {', 'void main() {',
'vNormal = aNormal;', 'vec3 pos = aPos;',
'vec3 n = aNormal;',
'if (uCurvatureOn > 0.5) {',
'vec2 d = pos.xz - uCamPos.xz;',
'float r = max(1.0, uEarthRadius);',
'pos.y -= dot(d, d) / (2.0 * r);',
'n.x -= d.x / r;',
'n.z -= d.y / r;',
'n = normalize(n);',
'}',
'vNormal = n;',
'vUV = aUV;', 'vUV = aUV;',
'vY = aPos.y;', 'vY = pos.y;',
'vWorld = aPos;', 'vWorld = pos;',
'vec4 vp = uView * vec4(aPos, 1.0);', 'vec4 vp = uView * vec4(pos, 1.0);',
'vViewPos = vp.xyz;', 'vViewPos = vp.xyz;',
'gl_Position = uProj * vp;', 'gl_Position = uProj * vp;',
'}' '}'
@@ -888,6 +901,8 @@ function init(canvas) {
var terrainUairColor = terrainProg ? gl.getUniformLocation(terrainProg, 'uAirColor') : null; var terrainUairColor = terrainProg ? gl.getUniformLocation(terrainProg, 'uAirColor') : null;
var terrainUairDensity = terrainProg ? gl.getUniformLocation(terrainProg, 'uAirDensity') : null; var terrainUairDensity = terrainProg ? gl.getUniformLocation(terrainProg, 'uAirDensity') : null;
var terrainUcampos = terrainProg ? gl.getUniformLocation(terrainProg, 'uCamPos') : null; var terrainUcampos = terrainProg ? gl.getUniformLocation(terrainProg, 'uCamPos') : null;
var terrainUEarthRadius = terrainProg ? gl.getUniformLocation(terrainProg, 'uEarthRadius') : 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 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;
@@ -958,7 +973,9 @@ function init(canvas) {
uSkyAmb: terrainUskyAmb, uAlbedoTint: terrainUalbedoTint, uSkyAmb: terrainUskyAmb, uAlbedoTint: terrainUalbedoTint,
uHorizonColor: terrainUhorizon, uHorizonColor: terrainUhorizon,
uAirColor: terrainUairColor, uAirDensity: terrainUairDensity, uAirColor: terrainUairColor, uAirDensity: terrainUairDensity,
uCamPos: terrainUcampos, uEdgeFadeTiles: terrainUedgeFade, uCamPos: terrainUcampos,
uEarthRadius: terrainUEarthRadius, uCurvatureOn: terrainUCurvatureOn,
uEdgeFadeTiles: terrainUedgeFade,
uStarAmb: terrainUstarAmb, uStarAmb: terrainUstarAmb,
uTime: terrainUtime, uCloudBot: terrainUcloudbot, uTime: terrainUtime, uCloudBot: terrainUcloudbot,
uCloudTop: terrainUcloudtop, uDensity: terrainUdensity, uCloudTop: terrainUcloudtop, uDensity: terrainUdensity,
@@ -2137,7 +2154,12 @@ var ATMO_MODEL_GRAY_TAU = (typeof ATMO_MODEL.grayTau === 'number')
? Math.max(0.1, Math.min(10.0, ATMO_MODEL.grayTau)) : 1.5; ? Math.max(0.1, Math.min(10.0, ATMO_MODEL.grayTau)) : 1.5;
var ATMO_MODEL_GAIN = (typeof ATMO_MODEL.gain === 'number') var ATMO_MODEL_GAIN = (typeof ATMO_MODEL.gain === 'number')
? Math.max(0.1, Math.min(5.0, ATMO_MODEL.gain)) : 2.0; ? Math.max(0.1, Math.min(5.0, ATMO_MODEL.gain)) : 2.0;
var EARTH_RADIUS_UNITS = 6371.0 / KM_PER_TILE; var CURV_CFG = (window.CONFIG && window.CONFIG.curvature) || {};
var CURVATURE_ON = CURV_CFG.enabled !== false;
var CURV_EXAG = (typeof CURV_CFG.exaggeration === 'number')
? Math.max(0.25, CURV_CFG.exaggeration) : 2.0;
var EARTH_RADIUS_UNITS = (typeof CURV_CFG.earthRadiusKm === 'number'
? Math.max(1000, CURV_CFG.earthRadiusKm) : 6371) / KM_PER_TILE / CURV_EXAG;
var ATMO_MODEL_BLUE_COLOR = new Float32Array([0.22, 0.42, 0.95]); 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]); var ATMO_MODEL_GRAY_COLOR = new Float32Array([0.72, 0.76, 0.82]);
// Integrated starlight + airglow. Physically this is about a millionth of // Integrated starlight + airglow. Physically this is about a millionth of
@@ -5490,6 +5512,8 @@ window.clouds3dRender = function(target) {
gl.uniform3f(terr.uAirColor, _air[0], _air[1], _air[2]); gl.uniform3f(terr.uAirColor, _air[0], _air[1], _air[2]);
gl.uniform1f(terr.uAirDensity, -Math.log(ATMO_HAZE_RESIDUAL) / Math.max(FOG_TILES, 0.001)); gl.uniform1f(terr.uAirDensity, -Math.log(ATMO_HAZE_RESIDUAL) / Math.max(FOG_TILES, 0.001));
gl.uniform3f(terr.uCamPos, camX, camY, camZ); gl.uniform3f(terr.uCamPos, camX, camY, camZ);
gl.uniform1f(terr.uEarthRadius, EARTH_RADIUS_UNITS);
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.bindBuffer(gl.ARRAY_BUFFER, terr.vbo); gl.bindBuffer(gl.ARRAY_BUFFER, terr.vbo);