Skip to content

Commit

Permalink
Add fog sky blending fix to cpu side
Browse files Browse the repository at this point in the history
  • Loading branch information
rreusser committed Apr 19, 2021
1 parent 91444e6 commit 2ef9db4
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 7 deletions.
3 changes: 3 additions & 0 deletions src/shaders/_prelude_fog.fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ vec3 tonemap(vec3 color) {

// Assumes z up and camera_dir *normalized* (to avoid computing its length multiple
// times for different functions).
// Must match definitions in:
// src/shaders/_prelude_fog.vertex.glsl#fog_sky_blending
// src/style/fog_helpers.js#getFogSkyBlending
float fog_sky_blending(vec3 camera_dir) {
float t = max(0.0, camera_dir.z / u_fog_sky_blend);
// Factor of 3 chosen to roughly match smoothstep.
Expand Down
3 changes: 2 additions & 1 deletion src/style/fog.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class Fog extends Evented {
get state(): FogState {
return {
range: this.properties.get('range'),
density: this.properties.get('density')
density: this.properties.get('density'),
skyBlend: this.properties.get('sky-blend')
};
}

Expand Down
21 changes: 15 additions & 6 deletions src/style/fog_helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,18 @@ export const FOG_SYMBOL_CLIPPING_THRESHOLD = 0.9;

export type FogState = {
range: [number, number],
density: number
density: number,
skyBlend: number
};

// As defined in _prelude_fog.fragment.glsl#fog_sky_blending
export function getFogSkyBlending(state: FogState, cameraDirection: Array<number>): number {
const t = Math.max(0.0, cameraDirection[2] / state.skyBlend);
return Math.exp(-3 * t * t);
}

// As defined in _prelude_fog.fragment.glsl#fog_opacity
export function getFogOpacity(state: FogState, depth: number, pitch: number): number {
export function getFogOpacity(state: FogState, pos: Array<number>, pitch: number): number {
const fogOpacity = smoothstep(FOG_PITCH_START, FOG_PITCH_END, pitch);
const [start, end] = state.range;
const fogDensity = state.density;
Expand All @@ -32,6 +39,7 @@ export function getFogOpacity(state: FogState, depth: number, pitch: number): nu
// https://www.desmos.com/calculator/3taufutxid
// The output of this function should match src/shaders/_prelude_fog.fragment.glsl
const decay = 6;
const depth = vec3.length(pos);
const t = (depth - start) / (end - start);
let falloff = 1.0 - Math.min(1, Math.exp(-decay * t));

Expand All @@ -47,24 +55,25 @@ export function getFogOpacity(state: FogState, depth: number, pitch: number): nu
// Account for fog density
falloff *= Math.pow(smoothstep(0, 1, t), fogExponent);

const cameraDirection = vec3.scale(vec3.create(), pos, 1.0 / depth);
falloff *= getFogSkyBlending(state, cameraDirection);

return falloff * fogOpacity;
}

export function getOpacityAtTileCoord(state: FogState, x: number, y: number, z: number, tileId: UnwrappedTileID, transform: Transform): number {
const mat = transform.calculateFogTileMatrix(tileId);
const pos = [x, y, z];
vec3.transformMat4(pos, pos, mat);
const depth = vec3.length(pos);

return getFogOpacity(state, depth, transform.pitch);
return getFogOpacity(state, pos, transform.pitch);
}

export function getFogOpacityAtLatLng(state: FogState, lngLat: LngLat, transform: Transform): number {
const meters = MercatorCoordinate.fromLngLat(lngLat);
const elevation = transform.elevation ? transform.elevation.getAtPoint(meters) : 0;
const pos = [meters.x, meters.y, elevation];
vec3.transformMat4(pos, pos, transform.mercatorFogMatrix);
const depth = vec3.length(pos);

return getFogOpacity(state, depth, transform.pitch);
return getFogOpacity(state, pos, transform.pitch);
}

0 comments on commit 2ef9db4

Please sign in to comment.