Skip to content

Commit

Permalink
[MAPS3D-916] reduce shader instruction count in fill-extrusion walls …
Browse files Browse the repository at this point in the history
…when flood lighting is enabled (#593)
  • Loading branch information
akoylasar authored Jun 9, 2023
1 parent 0342d1c commit d140ade
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 25 deletions.
8 changes: 4 additions & 4 deletions 3d-style/render/shadow_renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ function shadowDirectionFromProperties(transform: Transform, directionalLight: L
return vec3.fromValues(position.x, position.y, position.z);
}

function calculateGroundShadowFactor(directionalLight: Lights<Directional>, ambientLight: Lights<Ambient>): [number, number, number] {
export function calculateGroundShadowFactor(directionalLight: Lights<Directional>, ambientLight: Lights<Ambient>): [number, number, number] {
const dirColor = directionalLight.properties.get('color');
const dirIntensity = directionalLight.properties.get('intensity');
const dirDirection = directionalLight.properties.get('direction');
Expand All @@ -367,9 +367,9 @@ function calculateGroundShadowFactor(directionalLight: Lights<Directional>, ambi
// A: Ambient light coming into the surface; taking into account color and intensity
// D: Directional light coming into the surface; taking into account color, intensity and direction
const shadow = [
ambStrength[0] > 0.0 ? ambStrength[0] / (ambStrength[0] + dirStrength[0]) : 0.0,
ambStrength[1] > 0.0 ? ambStrength[1] / (ambStrength[1] + dirStrength[1]) : 0.0,
ambStrength[2] > 0.0 ? ambStrength[2] / (ambStrength[2] + dirStrength[2]) : 0.0
ambStrength[0] > 0.0 ? ambStrength[0] / (ambStrength[0] + dirStrength[0] + 1e-5) : 0.0,
ambStrength[1] > 0.0 ? ambStrength[1] / (ambStrength[1] + dirStrength[1] + 1e-5) : 0.0,
ambStrength[2] > 0.0 ? ambStrength[2] / (ambStrength[2] + dirStrength[2] + 1e-5) : 0.0
];

// Because blending will happen in sRGB space, convert the shadow factor to sRGB
Expand Down
8 changes: 2 additions & 6 deletions 3d-style/shaders/_prelude_shadow.fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,8 @@ float shadowed_light_factor(highp vec4 light_view_pos0, highp vec4 light_view_po
return 1.0 - (u_shadow_intensity * occlusion);
}

float shadow_occlusion(vec3 N, highp vec4 light_view_pos0, highp vec4 light_view_pos1, float view_depth) {
float NDotL = dot(N, u_shadow_direction);
if (NDotL < 0.0)
return 1.0;

float bias = calculate_shadow_bias(NDotL);
float shadow_occlusion(float ndotl, highp vec4 light_view_pos0, highp vec4 light_view_pos1, float view_depth) {
float bias = calculate_shadow_bias(ndotl);
return shadow_occlusion(light_view_pos0, light_view_pos1, view_depth, bias);
}

Expand Down
13 changes: 12 additions & 1 deletion src/render/draw_fill_extrusion.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Color from '../style-spec/util/color.js';
import Context from '../gl/context.js';
import {Terrain} from '../terrain/terrain.js';
import Tile from '../source/tile.js';
import {calculateGroundShadowFactor} from '../../3d-style/render/shadow_renderer.js';

import type Painter from './painter.js';
import type SourceCache from '../source/source_cache.js';
Expand Down Expand Up @@ -165,6 +166,15 @@ function drawExtrusionTiles(painter: Painter, source: SourceCache, layer: FillEx
const shadowRenderer = painter.shadowRenderer;
const drawDepth = isShadowPass && !!shadowRenderer;

let groundShadowFactor: [number, number, number] = [0, 0, 0];
if (shadowRenderer) {
const directionalLight = painter.style.directionalLight;
const ambientLight = painter.style.ambientLight;
if (directionalLight && ambientLight) {
groundShadowFactor = calculateGroundShadowFactor(directionalLight, ambientLight);
}
}

for (const coord of coords) {
const tile = source.getTile(coord);
const bucket: ?FillExtrusionBucket = (tile.getBucket(layer): any);
Expand Down Expand Up @@ -222,8 +232,9 @@ function drawExtrusionTiles(painter: Painter, source: SourceCache, layer: FillEx
uniformValues = fillExtrusionPatternUniformValues(matrix, painter, shouldUseVerticalGradient, opacity, ao, roofEdgeRadius, coord,
tile, heightLift, globeToMercator, mercatorCenter, invMatrix, floodLightColor, verticalScale);
} else {

uniformValues = fillExtrusionUniformValues(matrix, painter, shouldUseVerticalGradient, opacity, ao, roofEdgeRadius, coord,
heightLift, globeToMercator, mercatorCenter, invMatrix, floodLightColor, verticalScale, floodLightIntensity);
heightLift, globeToMercator, mercatorCenter, invMatrix, floodLightColor, verticalScale, floodLightIntensity, groundShadowFactor);
}
}

Expand Down
14 changes: 9 additions & 5 deletions src/render/program/fill_extrusion_program.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ export type FillExtrusionUniformsType = {|
'u_edge_radius': Uniform1f,
'u_flood_light_color': Uniform3f,
'u_vertical_scale': Uniform1f,
'u_flood_light_intensity': Uniform1f
'u_flood_light_intensity': Uniform1f,
'u_ground_shadow_factor': Uniform3f
|};

export type FillExtrusionDepthUniformsType = {|
Expand Down Expand Up @@ -97,7 +98,8 @@ const fillExtrusionUniforms = (context: Context): FillExtrusionUniformsType => (
'u_height_lift': new Uniform1f(context),
'u_flood_light_color': new Uniform3f(context),
'u_vertical_scale': new Uniform1f(context),
'u_flood_light_intensity': new Uniform1f(context)
'u_flood_light_intensity': new Uniform1f(context),
'u_ground_shadow_factor': new Uniform3f(context)
});

const fillExtrusionDepthUniforms = (context: Context): FillExtrusionDepthUniformsType => ({
Expand Down Expand Up @@ -158,7 +160,8 @@ const fillExtrusionUniformValues = (
invMatrix: Float32Array,
floodLightColor: [number, number, number],
verticalScale: number,
floodLightIntensity: number
floodLightIntensity: number,
groundShadowFactor: [number, number, number]
): UniformValues<FillExtrusionUniformsType> => {
const light = painter.style.light;
const _lp = light.properties.get('position');
Expand Down Expand Up @@ -190,7 +193,8 @@ const fillExtrusionUniformValues = (
'u_edge_radius': edgeRadius,
'u_flood_light_color': floodLightColor,
'u_vertical_scale': verticalScale,
'u_flood_light_intensity': floodLightIntensity
'u_flood_light_intensity': floodLightIntensity,
'u_ground_shadow_factor': groundShadowFactor
};

if (tr.projection.name === 'globe') {
Expand Down Expand Up @@ -235,7 +239,7 @@ const fillExtrusionPatternUniformValues = (
): UniformValues<FillExtrusionPatternUniformsType> => {
const uniformValues = fillExtrusionUniformValues(
matrix, painter, shouldUseVerticalGradient, opacity, aoIntensityRadius, edgeRadius, coord,
heightLift, zoomTransition, mercatorCenter, invMatrix, floodLightColor, verticalScale, 1.0);
heightLift, zoomTransition, mercatorCenter, invMatrix, floodLightColor, verticalScale, 1.0, [0, 0, 0]);
const heightFactorUniform = {
'u_height_factor': -Math.pow(2, coord.overscaledZ) / tile.tileSize / 8
};
Expand Down
8 changes: 2 additions & 6 deletions src/shaders/_prelude_lighting.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,10 @@ vec4 apply_lighting_with_emission_ground(vec4 color, float emissive_strength) {
return mix(apply_lighting_ground(color), color, emissive_strength);
}

vec3 apply_flood_lighting(vec3 flood_light_color, float fully_occluded_factor, float occlusion) {
highp vec3 ambient_contrib = u_lighting_ambient_color;
highp vec3 directional_contrib = u_lighting_directional_color * u_lighting_directional_dir.z;
vec3 shadow_factor = linearTosRGB(ambient_contrib / (ambient_contrib + directional_contrib + 1e-5));

vec3 compute_flood_lighting(vec3 flood_light_color, float fully_occluded_factor, float occlusion, vec3 ground_shadow_factor) {
// Compute final color by interpolating between the fully occluded
// and fully lit colors. Use a more steep ramp to avoid shadow acne on low angles.
vec3 fully_occluded_color = flood_light_color * mix(shadow_factor, vec3(1.0), fully_occluded_factor);
vec3 fully_occluded_color = flood_light_color * mix(ground_shadow_factor, vec3(1.0), fully_occluded_factor);
float occlusion_ramp = smoothstep(0.0, 0.2, 1.0 - occlusion);

return mix(fully_occluded_color, flood_light_color, occlusion_ramp);
Expand Down
8 changes: 5 additions & 3 deletions src/shaders/fill_extrusion.fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ varying highp vec3 v_normal;
uniform vec3 u_flood_light_color;
uniform highp float u_vertical_scale;
uniform float u_flood_light_intensity;
uniform vec3 u_ground_shadow_factor;

#if defined(LIGHTING_3D_MODE) && defined(FLOOD_LIGHT)
varying float v_flood_radius;
Expand Down Expand Up @@ -84,13 +85,14 @@ float flood_radiance = 0.0;
#endif // FLOOD_LIGHT
#ifdef RENDER_SHADOWS
#ifdef FLOOD_LIGHT
float ndotl = max(0.0, dot(normal, u_shadow_direction));
float occlusion = shadow_occlusion(normal, v_pos_light_view_0, v_pos_light_view_1, v_depth);
float ndotl_unclamped = dot(normal, u_shadow_direction);
float ndotl = max(0.0, ndotl_unclamped);
float occlusion = ndotl_unclamped < 0.0 ? 1.0 : shadow_occlusion(ndotl, v_pos_light_view_0, v_pos_light_view_1, v_depth);

// Compute both FE and flood lights separately and interpolate between the two.
// "litColor" uses pretty much "shadowed_light_factor_normal" as the directional component.
vec3 litColor = apply_lighting(color.rgb, normal, (1.0 - u_shadow_intensity * occlusion) * ndotl);
vec3 floodLitColor = apply_flood_lighting(u_flood_light_color * u_opacity, 1.0 - u_shadow_intensity, occlusion);
vec3 floodLitColor = compute_flood_lighting(u_flood_light_color * u_opacity, 1.0 - u_shadow_intensity, occlusion, u_ground_shadow_factor);

color.rgb = mix(litColor, floodLitColor, flood_radiance);
#else // FLOOD_LIGHT
Expand Down

0 comments on commit d140ade

Please sign in to comment.