Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shadow module UBO #9054

Merged
merged 11 commits into from
Aug 1, 2024
2 changes: 1 addition & 1 deletion modules/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export type {PickingInfo, GetPickingInfoParams} from './lib/picking/pick-info';
export type {ConstructorOf as _ConstructorOf} from './types/types';
export type {BinaryAttribute} from './lib/attribute/attribute';
export type {Effect, EffectContext, PreRenderOptions, PostRenderOptions} from './lib/effect';
export type {PickingUniforms, ProjectUniforms, UniformTypes} from './shaderlib/index';
export type {PickingUniforms, ProjectUniforms} from './shaderlib/index';
export type {DefaultProps} from './lifecycle/prop-types';
export type {LayersPassRenderOptions} from './passes/layers-pass';
export type {Widget, WidgetPlacement} from './lib/widget-manager';
Expand Down
20 changes: 20 additions & 0 deletions modules/core/src/lib/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,15 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
const {modelMatrix} = this.props;
this.setModuleParameters(moduleParameters);
const {
// shadow
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concern:

  • That is a lot of individual imports, kind of pollutes to have such a big surface area from a leaf functionality into a core file.
  • Same for terrain I suppose though I didn't catch it then.
  • Is there a way things can be made more decoupled or pluggable. Some function to get the props, instead of requiring layer class to be aware of them all?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, I have a TODO to review it once the UBO migration is complete. I chose to do it here as this is where setModuleParameters is being invoked in the same way.

Some of the other modules are already self-contained, like the MaskExtension, so I expect we will be able to tidy this up. First though I would like to remove all the updateModuleSettings calls before potentially changing the data flow in the code.

I have added this point to the Audit Log as suggested

shadowEnabled,
drawToShadowMap,
shadowMaps,
dummyShadowMap,
shadowColor,
shadowMatrices,
shadowLightId,
// terrain
picking,
heightMap,
heightMapBounds,
Expand All @@ -1088,6 +1097,16 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
useTerrainHeightMap,
terrainSkipRender
} = moduleParameters;
const shadowProps = {
viewport,
shadowEnabled,
drawToShadowMap,
shadowMaps,
dummyShadowMap,
shadowColor,
shadowMatrices,
shadowLightId
};
const terrainProps = {
viewport,
picking,
Expand All @@ -1101,6 +1120,7 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
};
this.setShaderModuleProps({
// TODO Revisit whether this is necessary once all layers ported to UBO
shadow: shadowProps,
terrain: terrainProps,
layer: {opacity},
picking: {isActive, isAttribute} as PickingProps,
Expand Down
1 change: 0 additions & 1 deletion modules/core/src/shaderlib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ export {layerUniforms, picking, project, project32, gouraudLighting, phongLighti

// Useful for custom shader modules
export type {ProjectUniforms} from './project/viewport-uniforms';
export type {UniformTypes} from './misc/uniform-types';

// TODO - these should be imported from luma.gl
/* eslint-disable camelcase */
Expand Down
30 changes: 0 additions & 30 deletions modules/core/src/shaderlib/misc/uniform-types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
import type {Matrix3, Matrix4, Vector2, Vector3, Vector4} from '@math.gl/core';

type UniformProps = {
[name: string]: number | boolean | number[];
};

type NumArray2 = [number, number];
type NumArray3 = [number, number, number];
type NumArray4 = [number, number, number, number];
Expand Down Expand Up @@ -42,27 +36,3 @@ export type NumArray16 = [
number,
number
];

type UniformType<ValueT extends number | boolean | number[]> = ValueT extends number | boolean
? 'f32' | 'i32' | 'u32'
: ValueT extends NumArray2 | Vector2
? 'vec2<f32>' | 'vec2<i32>' | 'vec2<u32>'
: ValueT extends NumArray3 | Vector3
? 'vec3<f32>' | 'vec3<i32>' | 'vec3<u32>'
: ValueT extends NumArray4 | Vector4
? 'vec4<f32>' | 'vec4<i32>' | 'vec4<u32>' | 'mat2x2<f32>'
: ValueT extends NumArray6
? 'mat2x3<f32>' | 'mat3x2<f32>'
: ValueT extends NumArray8
? 'mat2x4<f32>' | 'mat4x2<f32>'
: ValueT extends NumArray9 | Matrix3
? 'mat3x3<f32>'
: ValueT extends NumArray12
? 'mat3x4<f32>' | 'mat4x3<f32>'
: ValueT extends NumArray16 | Matrix4
? 'mat4x4<f32>'
: never;

export type UniformTypes<PropsT extends UniformProps> = {
[name in keyof PropsT]: UniformType<PropsT[name]>;
};
164 changes: 118 additions & 46 deletions modules/core/src/shaderlib/shadow/shadow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,44 @@ import memoize from '../../utils/memoize';
import {pixelsToWorld} from '@math.gl/web-mercator';

import type {Texture} from '@luma.gl/core';
import type {ShaderModule} from '@luma.gl/shadertools';
import {glsl, ShaderModule} from '@luma.gl/shadertools';
import type Viewport from '../../viewports/viewport';
import type {ProjectUniforms} from '../project/viewport-uniforms';

const vs = `
const uniformBlock = glsl`
uniform shadowUniforms {
bool drawShadowMap;
bool useShadowMap;
vec4 color;
highp int lightId;
float lightCount;
mat4 viewProjectionMatrix0;
mat4 viewProjectionMatrix1;
vec4 projectCenter0;
vec4 projectCenter1;
} shadow;
`;

const vertex = glsl`
const int max_lights = 2;
uniform mat4 shadow_uViewProjectionMatrices[max_lights];
uniform vec4 shadow_uProjectCenters[max_lights];
uniform bool shadow_uDrawShadowMap;
uniform bool shadow_uUseShadowMap;
uniform int shadow_uLightId;
uniform float shadow_uLightCount;

out vec3 shadow_vPosition[max_lights];

vec4 shadow_setVertexPosition(vec4 position_commonspace) {
if (shadow_uDrawShadowMap) {
return project_common_position_to_clipspace(position_commonspace, shadow_uViewProjectionMatrices[shadow_uLightId], shadow_uProjectCenters[shadow_uLightId]);
mat4 viewProjectionMatrices[max_lights];
viewProjectionMatrices[0] = shadow.viewProjectionMatrix0;
viewProjectionMatrices[1] = shadow.viewProjectionMatrix1;
vec4 projectCenters[max_lights];
projectCenters[0] = shadow.projectCenter0;
projectCenters[1] = shadow.projectCenter1;

if (shadow.drawShadowMap) {
return project_common_position_to_clipspace(position_commonspace, viewProjectionMatrices[shadow.lightId], projectCenters[shadow.lightId]);
}
if (shadow_uUseShadowMap) {
if (shadow.useShadowMap) {
for (int i = 0; i < max_lights; i++) {
if(i < int(shadow_uLightCount)) {
vec4 shadowMap_position = project_common_position_to_clipspace(position_commonspace, shadow_uViewProjectionMatrices[i], shadow_uProjectCenters[i]);
if(i < int(shadow.lightCount)) {
vec4 shadowMap_position = project_common_position_to_clipspace(position_commonspace, viewProjectionMatrices[i], projectCenters[i]);
shadow_vPosition[i] = (shadowMap_position.xyz / shadowMap_position.w + 1.0) / 2.0;
}
}
Expand All @@ -56,14 +71,15 @@ vec4 shadow_setVertexPosition(vec4 position_commonspace) {
}
`;

const fs = `
const vs = `
${uniformBlock}
${vertex}
`;

const fragment = glsl`
const int max_lights = 2;
uniform bool shadow_uDrawShadowMap;
uniform bool shadow_uUseShadowMap;
uniform sampler2D shadow_uShadowMap0;
uniform sampler2D shadow_uShadowMap1;
uniform vec4 shadow_uColor;
uniform float shadow_uLightCount;

in vec3 shadow_vPosition[max_lights];

Expand All @@ -79,46 +95,68 @@ float shadow_getShadowWeight(vec3 position, sampler2D shadowMap) {
}

vec4 shadow_filterShadowColor(vec4 color) {
if (shadow_uDrawShadowMap) {
if (shadow.drawShadowMap) {
vec4 rgbaDepth = fract(gl_FragCoord.z * bitPackShift);
rgbaDepth -= rgbaDepth.gbaa * bitMask;
return rgbaDepth;
}
if (shadow_uUseShadowMap) {
if (shadow.useShadowMap) {
float shadowAlpha = 0.0;
shadowAlpha += shadow_getShadowWeight(shadow_vPosition[0], shadow_uShadowMap0);
if(shadow_uLightCount > 1.0) {
if(shadow.lightCount > 1.0) {
shadowAlpha += shadow_getShadowWeight(shadow_vPosition[1], shadow_uShadowMap1);
}
shadowAlpha *= shadow_uColor.a / shadow_uLightCount;
shadowAlpha *= shadow.color.a / shadow.lightCount;
float blendedAlpha = shadowAlpha + color.a * (1.0 - shadowAlpha);

return vec4(
mix(color.rgb, shadow_uColor.rgb, shadowAlpha / blendedAlpha),
mix(color.rgb, shadow.color.rgb, shadowAlpha / blendedAlpha),
blendedAlpha
);
}
return color;
}
`;

const fs = `
${uniformBlock}
${fragment}
`;

const getMemoizedViewportCenterPosition = memoize(getViewportCenterPosition);
const getMemoizedViewProjectionMatrices = memoize(getViewProjectionMatrices);

const DEFAULT_SHADOW_COLOR = [0, 0, 0, 1.0];
const DEFAULT_SHADOW_COLOR: NumberArray4 = [0, 0, 0, 1.0];
const VECTOR_TO_POINT_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0];

type ShadowModuleSettings = {
type ShadowModuleProps = {
viewport: Viewport;
shadowEnabled?: boolean;
drawToShadowMap?: boolean;
shadowMaps?: Texture[];
dummyShadowMap?: Texture;
shadowColor?: number[];
dummyShadowMap: Texture;
shadowColor?: NumberArray4;
shadowMatrices?: Matrix4[];
shadowLightId?: number;
};

type ShadowModuleUniforms = {
drawShadowMap: boolean;
useShadowMap: boolean;
color?: NumberArray4;
lightId?: number;
lightCount?: number;
viewProjectionMatrix0?: NumberArray16;
viewProjectionMatrix1?: NumberArray16;
projectCenter0?: NumberArray4;
projectCenter1?: NumberArray4;
};

type ShadowModuleBindings = {
shadow_uShadowMap0: Texture;
shadow_uShadowMap1: Texture;
};

function screenToCommonSpace(xyz: number[], pixelUnprojectionMatrix: number[]): number[] {
const [x, y, z] = xyz;
const coord = pixelsToWorld([x, y, z], pixelUnprojectionMatrix);
Expand Down Expand Up @@ -183,29 +221,21 @@ function getViewProjectionMatrices({

// eslint-disable-next-line complexity
function createShadowUniforms(
opts: ShadowModuleSettings,
context: ProjectUniforms
): Record<string, any> {
opts: ShadowModuleProps
): ShadowModuleBindings & ShadowModuleUniforms {
const {shadowEnabled = true} = opts;
if (!shadowEnabled || !opts.shadowMatrices || !opts.shadowMatrices.length) {
return {
shadow_uDrawShadowMap: false,
shadow_uUseShadowMap: false,
drawShadowMap: false,
useShadowMap: false,
shadow_uShadowMap0: opts.dummyShadowMap,
shadow_uShadowMap1: opts.dummyShadowMap
};
}
const uniforms = {
shadow_uDrawShadowMap: Boolean(opts.drawToShadowMap),
shadow_uUseShadowMap: opts.shadowMaps ? opts.shadowMaps.length > 0 : false,
shadow_uColor: opts.shadowColor || DEFAULT_SHADOW_COLOR,
shadow_uLightId: opts.shadowLightId || 0,
shadow_uLightCount: opts.shadowMatrices.length
};

const projectUniforms = project.getUniforms(opts) as ProjectUniforms;
const center = getMemoizedViewportCenterPosition({
viewport: opts.viewport,
center: context.center
center: projectUniforms.center
});

const projectCenters: NumericArray[] = [];
Expand All @@ -221,8 +251,8 @@ function createShadowUniforms(
.translate(new Vector3(opts.viewport.center).negate());

if (
context.coordinateSystem === COORDINATE_SYSTEM.LNGLAT &&
context.projectionMode === PROJECTION_MODE.WEB_MERCATOR
projectUniforms.coordinateSystem === COORDINATE_SYSTEM.LNGLAT &&
projectUniforms.projectionMode === PROJECTION_MODE.WEB_MERCATOR
) {
viewProjectionMatrices[i] = viewProjectionMatrixCentered;
projectCenters[i] = center;
Expand All @@ -234,9 +264,19 @@ function createShadowUniforms(
}
}

const uniforms = {
drawShadowMap: Boolean(opts.drawToShadowMap),
useShadowMap: opts.shadowMaps ? opts.shadowMaps.length > 0 : false,
color: opts.shadowColor || DEFAULT_SHADOW_COLOR,
lightId: opts.shadowLightId || 0,
lightCount: opts.shadowMatrices.length,
shadow_uShadowMap0: opts.dummyShadowMap,
shadow_uShadowMap1: opts.dummyShadowMap
};

for (let i = 0; i < viewProjectionMatrices.length; i++) {
uniforms[`shadow_uViewProjectionMatrices[${i}]`] = viewProjectionMatrices[i];
uniforms[`shadow_uProjectCenters[${i}]`] = projectCenters[i];
uniforms[`viewProjectionMatrix${i}`] = viewProjectionMatrices[i];
uniforms[`projectCenter${i}`] = projectCenters[i];
}

for (let i = 0; i < 2; i++) {
Expand Down Expand Up @@ -271,5 +311,37 @@ export default {
return createShadowUniforms(opts, context);
}
return {};
},
uniformTypes: {
drawShadowMap: 'f32',
useShadowMap: 'f32',
color: 'vec4<f32>',
lightId: 'i32',
lightCount: 'f32',
viewProjectionMatrix0: 'mat4x4<f32>',
viewProjectionMatrix1: 'mat4x4<f32>',
projectCenter0: 'vec4<f32>',
projectCenter1: 'vec4<f32>'
}
} as const satisfies ShaderModule<ShadowModuleSettings>;
} as const satisfies ShaderModule<ShadowModuleProps, ShadowModuleUniforms, ShadowModuleBindings>;

// TODO replace with type from math.gl
type NumberArray4 = [number, number, number, number];
type NumberArray16 = [
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number
];
4 changes: 2 additions & 2 deletions modules/extensions/src/clip/clip-extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import type {ShaderModule} from '@luma.gl/shadertools';
import {LayerExtension} from '@deck.gl/core';

import type {Layer, UniformTypes} from '@deck.gl/core';
import type {Layer} from '@deck.gl/core';
import {glsl} from '../utils/syntax-tags';

const defaultProps = {
Expand Down Expand Up @@ -64,7 +64,7 @@ const shaderModuleVs: ShaderModule<ClipModuleProps> = {
vs: shaderFunction,
uniformTypes: {
bounds: 'vec4<f32>'
} as const satisfies UniformTypes<ClipModuleProps>
}
};

const injectionVs = {
Expand Down
4 changes: 2 additions & 2 deletions modules/extensions/src/collision-filter/shader-module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Framebuffer, Texture, TextureView} from '@luma.gl/core';
import type {ShaderModule} from '@luma.gl/shadertools';
import {project, UniformTypes} from '@deck.gl/core';
import {project} from '@deck.gl/core';
import {glsl} from '../utils/syntax-tags';

const vs = glsl`
Expand Down Expand Up @@ -120,5 +120,5 @@ export default {
uniformTypes: {
sort: 'i32',
enabled: 'i32'
} as const satisfies UniformTypes<CollisionUniforms>
}
} as ShaderModule<CollisionModuleProps>;
Loading
Loading