Skip to content

Commit

Permalink
Simplify and consolidate globe atmosphere uniforms (#11756)
Browse files Browse the repository at this point in the history
* Reduce frequency of calculation for globe uniforms

* Fix flow

* Reconstruct horizon direction in shader

* Address review comment

* Simplify + Lint

Fixup

* Fix typo
  • Loading branch information
karimnaaji authored Apr 21, 2022
1 parent c6e7672 commit 6971327
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 71 deletions.
17 changes: 15 additions & 2 deletions src/geo/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ class Transform {
// globe coordinate transformation matrix
globeMatrix: Float64Array;

globeCenterInViewSpace: [number, number, number];
globeRadius: number;

inverseAdjustmentMatrix: Array<number>;

minLng: number;
Expand Down Expand Up @@ -178,6 +181,8 @@ class Transform {
this._averageElevation = 0;
this.cameraElevationReference = "ground";
this._projectionScaler = 1.0;
this.globeRadius = 0;
this.globeCenterInViewSpace = [0, 0, 0];

// Move the horizon closer to the center. 0 would not shift the horizon. 1 would put the horizon at the center.
this._horizonShift = 0.1;
Expand Down Expand Up @@ -1767,8 +1772,16 @@ class Transform {
if (!m) throw new Error("failed to invert matrix");
this.pixelMatrixInverse = m;

// globe matrix
this.globeMatrix = this.projection.name === 'globe' ? calculateGlobeMatrix(this) : m;
if (this.projection.name === 'globe') {
this.globeMatrix = calculateGlobeMatrix(this);

const globeCenter = [this.globeMatrix[12], this.globeMatrix[13], this.globeMatrix[14]];

this.globeCenterInViewSpace = vec3.transformMat4(globeCenter, globeCenter, worldToCamera);
this.globeRadius = this.worldSize / 2.0 / Math.PI - 1.0;
} else {
this.globeMatrix = m;
}

this._projMatrixCache = {};
this._alignedProjMatrixCache = {};
Expand Down
23 changes: 3 additions & 20 deletions src/render/draw_atmosphere.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ import Fog from '../style/fog.js';

export default drawAtmosphere;

function project(point, m) {
return vec3.transformMat4(point, point, m);
}

function drawAtmosphere(painter: Painter, fog: Fog) {
const context = painter.context;
const gl = context.gl;
Expand All @@ -26,16 +22,6 @@ function drawAtmosphere(painter: Painter, fog: Fog) {
const defines = tr.projection.name === 'globe' ? ['PROJECTION_GLOBE_VIEW', 'FOG'] : ['FOG'];
const program = painter.useProgram('globeAtmosphere', null, ((defines: any): DynamicDefinesType[]));

// Render the gradient atmosphere by casting rays from screen pixels and determining their
// closest distance to the globe. This is done in view space where camera is located in the origo
// facing -z direction.
const zUnit = tr.projection.zAxisUnit === "meters" ? tr.pixelsPerMeter : 1.0;
const viewMatrix = tr._camera.getWorldToCamera(tr.worldSize, zUnit);

const center = [tr.globeMatrix[12], tr.globeMatrix[13], tr.globeMatrix[14]];
const globeCenterInViewSpace = project(center, viewMatrix);
const globeRadius = tr.worldSize / 2.0 / Math.PI - 1.0;

const transitionT = globeToMercatorTransition(tr.zoom);

const fogColor = fog.properties.get('color').toArray01();
Expand All @@ -57,20 +43,17 @@ function drawAtmosphere(painter: Painter, fog: Fog) {
const horizonBlend = mapValue(fog.properties.get('horizon-blend'), 0.0, 1.0, 0.0, 0.25);

const temporalOffset = (painter.frameCounter / 1000.0) % 1;

const globeCenterInViewSpace = (((tr.globeCenterInViewSpace): any): Array<number>);
const globeCenterDistance = vec3.length(globeCenterInViewSpace);
const distanceToHorizon = Math.sqrt(Math.pow(globeCenterDistance, 2.0) - Math.pow(globeRadius, 2.0));
const distanceToHorizon = Math.sqrt(Math.pow(globeCenterDistance, 2.0) - Math.pow(tr.globeRadius, 2.0));
const horizonAngle = Math.acos(distanceToHorizon / globeCenterDistance);

const uniforms = atmosphereUniformValues(
tr.frustumCorners.TL,
tr.frustumCorners.TR,
tr.frustumCorners.BR,
tr.frustumCorners.BL,
tr.frustumCorners.horizonL,
tr.frustumCorners.horizonR,
globeCenterInViewSpace,
globeRadius,
tr.frustumCorners.horizon,
transitionT,
horizonBlend,
fogColor,
Expand Down
29 changes: 11 additions & 18 deletions src/render/painter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import browser from '../util/browser.js';
import window from '../util/window.js';

import {mat4, vec3} from 'gl-matrix';
import {mat4} from 'gl-matrix';
import SourceCache from '../source/source_cache.js';
import EXTENT from '../data/extent.js';
import pixelsToTileUnits from '../source/pixels_to_tile_units.js';
Expand Down Expand Up @@ -986,25 +986,18 @@ class Painter {
if (fog) {
const fogOpacity = fog.getOpacity(this.transform.pitch);
if (fogOpacity !== 0.0) {
const tr = this.transform;
const viewMatrix = tr._camera.getWorldToCamera(tr.worldSize, 1.0);
const center = [tr.globeMatrix[12], tr.globeMatrix[13], tr.globeMatrix[14]];
const globeCenterInViewSpace = vec3.transformMat4(center, center, viewMatrix);
const globeRadius = tr.worldSize / 2.0 / Math.PI - 1.0;
const viewport = [
tr.width * browser.devicePixelRatio,
tr.height * browser.devicePixelRatio
];

const fogUniforms = fogUniformValues(
this, fog, tileID, fogOpacity,
tr.frustumCorners.TL,
tr.frustumCorners.TR,
tr.frustumCorners.BR,
tr.frustumCorners.BL,
globeCenterInViewSpace,
globeRadius,
viewport);
this.transform.frustumCorners.TL,
this.transform.frustumCorners.TR,
this.transform.frustumCorners.BR,
this.transform.frustumCorners.BL,
this.transform.globeCenterInViewSpace,
this.transform.globeRadius,
[
this.transform.width * browser.devicePixelRatio,
this.transform.height * browser.devicePixelRatio
]);

program.setFogUniformValues(context, fogUniforms);
}
Expand Down
12 changes: 8 additions & 4 deletions src/shaders/atmosphere.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@ uniform vec3 u_frustum_tl;
uniform vec3 u_frustum_tr;
uniform vec3 u_frustum_br;
uniform vec3 u_frustum_bl;
uniform vec3 u_horizon_l;
uniform vec3 u_horizon_r;
uniform float u_horizon;

varying highp vec3 v_ray_dir;
varying highp vec3 v_horizon_dir;

void main() {
v_ray_dir = mix(mix(u_frustum_tl, u_frustum_tr, a_uv.x),
v_ray_dir = mix(
mix(u_frustum_tl, u_frustum_tr, a_uv.x),
mix(u_frustum_bl, u_frustum_br, a_uv.x),
a_uv.y);
v_horizon_dir = mix(u_horizon_l, u_horizon_r, a_uv.x);

v_horizon_dir = mix(
mix(u_frustum_tl, u_frustum_bl, u_horizon),
mix(u_frustum_tr, u_frustum_br, u_horizon),
a_uv.x);

gl_Position = vec4(a_pos, 1.0);
}
24 changes: 6 additions & 18 deletions src/terrain/globe_raster_program.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ export type AtmosphereUniformsType = {|
'u_frustum_tr': Uniform3f,
'u_frustum_br': Uniform3f,
'u_frustum_bl': Uniform3f,
'u_horizon_l': Uniform3f,
'u_horizon_r': Uniform3f,
'u_globe_pos': Uniform3f,
'u_globe_radius': Uniform1f,
'u_horizon': Uniform1f,
'u_transition': Uniform1f,
'u_fadeout_range': Uniform1f,
'u_color': Uniform4f,
Expand Down Expand Up @@ -61,10 +58,7 @@ const atmosphereUniforms = (context: Context, locations: UniformLocations): Atmo
'u_frustum_tr': new Uniform3f(context, locations.u_frustum_tr),
'u_frustum_br': new Uniform3f(context, locations.u_frustum_br),
'u_frustum_bl': new Uniform3f(context, locations.u_frustum_bl),
'u_horizon_l': new Uniform3f(context, locations.u_horizon_l),
'u_horizon_r': new Uniform3f(context, locations.u_horizon_r),
'u_globe_pos': new Uniform3f(context, locations.u_globe_pos),
'u_globe_radius': new Uniform1f(context, locations.u_globe_radius),
'u_horizon': new Uniform1f(context, locations.u_horizon),
'u_transition': new Uniform1f(context, locations.u_transition),
'u_fadeout_range': new Uniform1f(context, locations.u_fadeout_range),
'u_color': new Uniform4f(context, locations.u_color),
Expand Down Expand Up @@ -100,14 +94,11 @@ const atmosphereUniformValues = (
frustumDirTr: [number, number, number],
frustumDirBr: [number, number, number],
frustumDirBl: [number, number, number],
horizonL: [number, number, number],
horizonR: [number, number, number],
globePosition: [number, number, number],
globeRadius: number,
horizon: number,
transitionT: number,
fadeoutRange: number,
color: [number, number, number, number],
skyColor: [number, number, number, number],
highColor: [number, number, number, number],
spaceColor: [number, number, number, number],
starIntensity: number,
temporalOffset: number,
Expand All @@ -118,14 +109,11 @@ const atmosphereUniformValues = (
'u_frustum_tr': frustumDirTr,
'u_frustum_br': frustumDirBr,
'u_frustum_bl': frustumDirBl,
'u_horizon_r': horizonR,
'u_horizon_l': horizonL,
'u_globe_pos': globePosition,
'u_globe_radius': globeRadius,
'u_horizon': horizon,
'u_transition': transitionT,
'u_fadeout_range': fadeoutRange,
'u_color': color,
'u_high_color': skyColor,
'u_high_color': highColor,
'u_space_color': spaceColor,
'u_star_intensity': starIntensity,
'u_star_size': 5.0 * browser.devicePixelRatio,
Expand Down
13 changes: 4 additions & 9 deletions src/util/primitives.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,14 @@ class FrustumCorners {
TR: [number, number, number];
BR: [number, number, number];
BL: [number, number, number];
horizonL: [number, number, number];
horizonR: [number, number, number];
horizon: number;

constructor(TL_: [number, number, number], TR_: [number, number, number], BR_: [number, number, number], BL_: [number, number, number], horizonL_: [number, number, number], horizonR_: [number, number, number]) {
constructor(TL_: [number, number, number], TR_: [number, number, number], BR_: [number, number, number], BL_: [number, number, number], horizon_: number) {
this.TL = TL_;
this.TR = TR_;
this.BR = BR_;
this.BL = BL_;
this.horizonL = horizonL_;
this.horizonR = horizonR_;
this.horizon = horizon_;
}

static fromInvProjectionMatrix(invProj: Array<number>, horizonFromTop: number, viewportHeight: number): FrustumCorners {
Expand All @@ -113,10 +111,7 @@ class FrustumCorners {
const BR = vec3.transformMat4(BRClip, BRClip, invProj);
const BL = vec3.transformMat4(BLClip, BLClip, invProj);

const horizonL = vec3.lerp([0, 0, 0], TL, BL, horizonFromTop / viewportHeight);
const horizonR = vec3.lerp([0, 0, 0], TR, BR, horizonFromTop / viewportHeight);

return new FrustumCorners(TL, TR, BR, BL, horizonL, horizonR);
return new FrustumCorners(TL, TR, BR, BL, horizonFromTop / viewportHeight);
}
}

Expand Down

0 comments on commit 6971327

Please sign in to comment.