diff --git a/docs/api-reference/aggregation-layers/aggregator.md b/docs/api-reference/aggregation-layers/aggregator.md index d91c442b6af..72b90241b68 100644 --- a/docs/api-reference/aggregation-layers/aggregator.md +++ b/docs/api-reference/aggregation-layers/aggregator.md @@ -86,7 +86,7 @@ aggregator.update(); Called before the result buffers are drawn to screen. Certain types of aggregations are dependent on render time context and this is alternative opportunity to update just-in-time. ```ts -aggregator.preDraw({moduleSettings: ...}); +aggregator.preDraw(); ``` #### `getBin` {#getbin} diff --git a/modules/aggregation-layers/src/common/aggregation-layer.ts b/modules/aggregation-layers/src/common/aggregation-layer.ts index e64f1c0b325..9d4ab4f4ade 100644 --- a/modules/aggregation-layers/src/common/aggregation-layer.ts +++ b/modules/aggregation-layers/src/common/aggregation-layer.ts @@ -86,12 +86,15 @@ export default abstract class AggregationLayer< aggregator.update(); } - draw({moduleParameters}) { - // GPU aggregation needs `moduleSettings` for projection/filter uniforms which are only accessible at draw time + draw({shaderModuleProps}) { + // GPU aggregation needs `shaderModuleProps` for projection/filter uniforms which are only accessible at draw time // GPUAggregator's Buffers are pre-allocated during `update()` and passed down to the sublayer attributes in renderLayers() // Although the Buffers have been bound to the sublayer's Model, their content are not populated yet // GPUAggregator.preDraw() is called in the draw cycle here right before Buffers are used by sublayer.draw() - this.state.aggregator.preDraw({moduleSettings: moduleParameters}); + const {aggregator} = this.state; + // @ts-expect-error only used by GPU aggregators + aggregator.setProps({shaderModuleProps}); + aggregator.preDraw(); } // override CompositeLayer._getAttributeManager to create AttributeManager instance diff --git a/modules/aggregation-layers/src/common/aggregator/aggregator.ts b/modules/aggregation-layers/src/common/aggregator/aggregator.ts index 651d6861202..41ef6d960c6 100644 --- a/modules/aggregation-layers/src/common/aggregator/aggregator.ts +++ b/modules/aggregation-layers/src/common/aggregator/aggregator.ts @@ -66,7 +66,7 @@ export interface Aggregator { update(): void; /** Called before layer is drawn to screen. */ - preDraw(params?: {moduleSettings: any}): void; + preDraw(): void; /** Dispose all allocated resources */ destroy(): void; diff --git a/modules/aggregation-layers/src/common/aggregator/gpu-aggregator/webgl-aggregator.ts b/modules/aggregation-layers/src/common/aggregator/gpu-aggregator/webgl-aggregator.ts index 95bd622b76d..70879da9293 100644 --- a/modules/aggregation-layers/src/common/aggregator/gpu-aggregator/webgl-aggregator.ts +++ b/modules/aggregation-layers/src/common/aggregator/gpu-aggregator/webgl-aggregator.ts @@ -42,7 +42,7 @@ type WebGLAggregationProps = AggregationProps & { */ binIdRange: [start: number, end: number][]; /** Context props passed to the shader modules */ - moduleSettings?: ModelProps['moduleSettings']; + shaderModuleProps?: Record; }; /** An Aggregator implementation that calculates aggregation on the GPU */ @@ -221,8 +221,8 @@ export class WebGLAggregator implements Aggregator { } this.binSorter.setModelProps({attributes: attributeBuffers, constantAttributes}); } - if (props.moduleSettings) { - this.binSorter.setModelProps({moduleSettings: props.moduleSettings}); + if (props.shaderModuleProps) { + this.binSorter.setModelProps({shaderModuleProps: props.shaderModuleProps}); } Object.assign(this.props, props); @@ -245,20 +245,11 @@ export class WebGLAggregator implements Aggregator { update() {} /** Run aggregation */ - preDraw( - /** Parameters only available at runtime */ - opts: { - moduleSettings: any; - } - ) { + preDraw() { if (!this.needsUpdate.some(Boolean)) { return; } - if (opts.moduleSettings) { - this.binSorter.setModelProps({moduleSettings: opts.moduleSettings}); - } - const {operations} = this.props; const operationsToUpdate = this.needsUpdate.map((needsUpdate, i) => needsUpdate ? operations[i] : null diff --git a/modules/aggregation-layers/src/common/aggregator/gpu-aggregator/webgl-bin-sorter.ts b/modules/aggregation-layers/src/common/aggregator/gpu-aggregator/webgl-bin-sorter.ts index cc57dc639c7..15d0f6038f4 100644 --- a/modules/aggregation-layers/src/common/aggregator/gpu-aggregator/webgl-bin-sorter.ts +++ b/modules/aggregation-layers/src/common/aggregator/gpu-aggregator/webgl-bin-sorter.ts @@ -89,10 +89,9 @@ export class WebGLBinSorter { } setModelProps( - props: Pick< - ModelProps, - 'moduleSettings' | 'vertexCount' | 'uniforms' | 'attributes' | 'constantAttributes' - > + props: Pick & { + shaderModuleProps?: Record; + } ) { const model = this.model; if (props.attributes) { @@ -104,18 +103,8 @@ export class WebGLBinSorter { if (props.vertexCount !== undefined) { model.setVertexCount(props.vertexCount); } - if (props.moduleSettings) { - const {viewport, devicePixelRatio, modelMatrix, coordinateSystem, coordinateOrigin} = - props.moduleSettings; - model.shaderInputs.setProps({ - project: { - viewport, - devicePixelRatio, - modelMatrix, - coordinateSystem, - coordinateOrigin - } - }); + if (props.shaderModuleProps) { + model.shaderInputs.setProps(props.shaderModuleProps); } } diff --git a/modules/aggregation-layers/src/contour-layer/contour-layer.ts b/modules/aggregation-layers/src/contour-layer/contour-layer.ts index e6a0de31d57..ded0d2acd82 100644 --- a/modules/aggregation-layers/src/contour-layer/contour-layer.ts +++ b/modules/aggregation-layers/src/contour-layer/contour-layer.ts @@ -286,8 +286,8 @@ export default class GridLayer extends override draw(opts) { // Replaces render time viewport with our own - if (opts.moduleParameters.viewport) { - opts.moduleParameters.viewport = this.state.aggregatorViewport; + if (opts.shaderModuleProps.project) { + opts.shaderModuleProps.project.viewport = this.state.aggregatorViewport; } super.draw(opts); } diff --git a/modules/aggregation-layers/src/grid-layer/grid-layer.ts b/modules/aggregation-layers/src/grid-layer/grid-layer.ts index 9bd822021c2..eb748d365f4 100644 --- a/modules/aggregation-layers/src/grid-layer/grid-layer.ts +++ b/modules/aggregation-layers/src/grid-layer/grid-layer.ts @@ -489,8 +489,8 @@ export default class GridLayer extends override draw(opts) { // Replaces render time viewport with our own - if (opts.moduleParameters.viewport) { - opts.moduleParameters.viewport = this.state.aggregatorViewport; + if (opts.shaderModuleProps.project) { + opts.shaderModuleProps.project.viewport = this.state.aggregatorViewport; } super.draw(opts); } diff --git a/modules/aggregation-layers/src/heatmap-layer/aggregation-layer.ts b/modules/aggregation-layers/src/heatmap-layer/aggregation-layer.ts index f5bbb878b1e..fbfe2b259ab 100644 --- a/modules/aggregation-layers/src/heatmap-layer/aggregation-layer.ts +++ b/modules/aggregation-layers/src/heatmap-layer/aggregation-layer.ts @@ -68,7 +68,7 @@ export default abstract class AggregationLayer< getModuleSettings() { // For regular layer draw this happens during draw cycle (_drawLayersInViewport) not during update cycle // For aggregation layers this is called during updateState to update aggregation data - // NOTE: it is similar to LayerPass._getModuleParameters() but doesn't inlcude `effects` it is not needed for aggregation + // NOTE: it is similar to LayerPass._getShaderModuleProps() but doesn't inlcude `effects` it is not needed for aggregation const {viewport, mousePosition, device} = this.context; const moduleSettings = Object.assign(Object.create(this.props), { viewport, diff --git a/modules/aggregation-layers/src/hexagon-layer/hexagon-layer.ts b/modules/aggregation-layers/src/hexagon-layer/hexagon-layer.ts index 19cc95bace2..27712f7cb2b 100644 --- a/modules/aggregation-layers/src/hexagon-layer/hexagon-layer.ts +++ b/modules/aggregation-layers/src/hexagon-layer/hexagon-layer.ts @@ -488,8 +488,8 @@ export default class HexagonLayer< override draw(opts) { // Replaces render time viewport with our own - if (opts.moduleParameters.viewport) { - opts.moduleParameters.viewport = this.state.aggregatorViewport; + if (opts.shaderModuleProps.project) { + opts.shaderModuleProps.project.viewport = this.state.aggregatorViewport; } super.draw(opts); } diff --git a/modules/carto/src/layers/post-process-utils.ts b/modules/carto/src/layers/post-process-utils.ts index 173b16cb0c0..dd09f728566 100644 --- a/modules/carto/src/layers/post-process-utils.ts +++ b/modules/carto/src/layers/post-process-utils.ts @@ -68,8 +68,8 @@ export function RTTModifier(BaseLayer) { static layerName = `RTT-${BaseLayer.layerName}`; draw(this: RTTLayer, opts: any) { - const {moduleParameters} = opts; - const {picking} = moduleParameters; + const {shaderModuleProps} = opts; + const {picking} = shaderModuleProps; const postProcessLayer = getPostProcessLayer(this); if (!picking.isActive) { @@ -134,10 +134,11 @@ export function PostProcessModifier fbo.resize({width, height})); } diff --git a/modules/core/src/effects/lighting/lighting-effect.ts b/modules/core/src/effects/lighting/lighting-effect.ts index f11e82d5a90..581fe09e288 100644 --- a/modules/core/src/effects/lighting/lighting-effect.ts +++ b/modules/core/src/effects/lighting/lighting-effect.ts @@ -11,9 +11,10 @@ import {Matrix4, Vector3} from '@math.gl/core'; import ShadowPass from '../../passes/shadow-pass'; import shadow from '../../shaderlib/shadow/shadow'; +import type {LightingProps} from '@luma.gl/shadertools'; +import type {ShadowModuleProps} from '../../shaderlib/shadow/shadow'; import type Layer from '../../lib/layer'; import type {Effect, EffectContext, PreRenderOptions} from '../../lib/effect'; -import {LightingProps} from '@luma.gl/shadertools'; const DEFAULT_AMBIENT_LIGHT_PROPS = { color: [255, 255, 255] as [number, number, number], @@ -117,34 +118,31 @@ export default class LightingEffect implements Effect { viewports, onViewportActive, views, - moduleParameters: { - shadowLightId: i, - dummyShadowMap: this.dummyShadowMap, - shadowMatrices: this.shadowMatrices + shaderModuleProps: { + shadow: { + shadowLightId: i, + dummyShadowMap: this.dummyShadowMap, + shadowMatrices: this.shadowMatrices + } } }); } } - getModuleParameters(layer: Layer) { - const parameters: { - lightSources?: LightingProps; - shadowMaps?: Texture[]; - dummyShadowMap?: Texture | null; - shadowColor?: [number, number, number, number]; - shadowMatrices?: Matrix4[]; - } = this.shadow - ? { + getShaderModuleProps(layer: Layer, otherShaderModuleProps: Record) { + const shadowProps = this.shadow + ? ({ + project: otherShaderModuleProps.project, shadowMaps: this.shadowPasses.map(shadowPass => shadowPass.getShadowMap()), - dummyShadowMap: this.dummyShadowMap, + dummyShadowMap: this.dummyShadowMap!, shadowColor: this.shadowColor, shadowMatrices: this.shadowMatrices - } + } satisfies ShadowModuleProps) : {}; // when not rendering to screen, turn off lighting by adding empty light source object // lights shader module relies on the `lightSources` to turn on/off lighting - parameters.lightSources = { + const lightingProps: LightingProps = { enabled: true, ambientLight: this.ambientLight, directionalLights: this.directionalLights.map(directionalLight => @@ -152,8 +150,15 @@ export default class LightingEffect implements Effect { ), pointLights: this.pointLights.map(pointLight => pointLight.getProjectedLight({layer})) }; - - return parameters; + // @ts-expect-error material is not a Layer prop + const materialProps = layer.props.material; + + return { + shadow: shadowProps, + lighting: lightingProps, + phongMaterial: materialProps, + gouraudMaterial: materialProps + }; } cleanup(context: EffectContext): void { diff --git a/modules/core/src/index.ts b/modules/core/src/index.ts index 72bdcb1a935..b76c565f2dd 100644 --- a/modules/core/src/index.ts +++ b/modules/core/src/index.ts @@ -125,7 +125,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} from './shaderlib/index'; +export type {PickingUniforms, ProjectProps, 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'; diff --git a/modules/core/src/lib/effect.ts b/modules/core/src/lib/effect.ts index 89c0df9bbaa..c6e7164bba6 100644 --- a/modules/core/src/lib/effect.ts +++ b/modules/core/src/lib/effect.ts @@ -32,7 +32,7 @@ export interface Effect { /** Called after layers are rendered to screen */ postRender?(opts: PostRenderOptions): Framebuffer | null; /** Module settings passed to models */ - getModuleParameters?(layer: Layer): any; + getShaderModuleProps?(layer: Layer, otherShaderModuleProps: Record): any; // / Lifecycle methods /** Called when this effect is added */ diff --git a/modules/core/src/lib/layer.ts b/modules/core/src/lib/layer.ts index bee85e0f9ee..f67bc6be166 100644 --- a/modules/core/src/lib/layer.ts +++ b/modules/core/src/lib/layer.ts @@ -39,7 +39,6 @@ import type {LayerContext} from './layer-manager'; import type {BinaryAttribute} from './attribute/attribute'; import {RenderPass} from '@luma.gl/core'; import {PickingProps} from '@luma.gl/shadertools'; -import {ProjectProps} from '../shaderlib/project/viewport-uniforms'; const TRACE_CHANGE_FLAG = 'layer.changeFlag'; const TRACE_INITIALIZE = 'layer.initialize'; @@ -1036,12 +1035,12 @@ export default abstract class Layer extends Component< // Calculates uniforms _drawLayer({ renderPass, - moduleParameters = null, + shaderModuleProps = null, uniforms = {}, parameters = {} }: { renderPass: RenderPass; - moduleParameters: any; + shaderModuleProps: any; uniforms: any; parameters: any; }): void { @@ -1054,94 +1053,11 @@ export default abstract class Layer extends Component< // @ts-ignore (TS2339) internalState is alwasy defined when this method is called this.props = this.internalState.propsInTransition || currentProps; - // apply gamma to opacity to make it visually "linear" - const opacity = Math.pow(this.props.opacity, 1 / 2.2); - uniforms.opacity = opacity; // TODO remove once layers ported to UBO - try { // TODO/ib - hack move to luma Model.draw - if (moduleParameters) { - const {isActive, isAttribute} = moduleParameters.picking; - const {viewport, devicePixelRatio, coordinateSystem, coordinateOrigin} = moduleParameters; - // @ts-expect-error material is not a Layer prop - const {material, modelMatrix} = this.props; - + if (shaderModuleProps) { this.setModuleParameters({}); - - const { - // mask - maskChannels, - maskMap, - maskSources, - // shadow - shadowEnabled, - drawToShadowMap, - shadowMaps, - dummyShadowMap, - shadowColor, - shadowMatrices, - shadowLightId, - // terrain - picking, - heightMap, - heightMapBounds, - dummyHeightMap, - terrainCover, - drawToTerrainHeightMap, - useTerrainHeightMap, - terrainSkipRender, - // lighting - lightSources - } = moduleParameters; - - const maskProps = { - maskChannels, - maskMap, - maskSources - }; - - const shadowProps = { - viewport, - shadowEnabled, - drawToShadowMap, - shadowMaps, - dummyShadowMap, - shadowColor, - shadowMatrices, - shadowLightId - }; - const terrainProps = { - viewport, - picking, - heightMap, - heightMapBounds, - dummyHeightMap, - terrainCover, - drawToTerrainHeightMap, - useTerrainHeightMap, - terrainSkipRender - }; - - const projectProps = { - viewport, - devicePixelRatio, - modelMatrix, - coordinateSystem, - coordinateOrigin - } as ProjectProps; - - this.setShaderModuleProps({ - // TODO Revisit whether this is necessary once all layers ported to UBO - mask: maskProps, - shadow: shadowProps, - terrain: terrainProps, - layer: {opacity}, - lighting: lightSources, - phongMaterial: material, - gouraudMaterial: material, - picking: {isActive, isAttribute} as const satisfies PickingProps, - project: projectProps - }); + this.setShaderModuleProps(shaderModuleProps); } // Apply polygon offset to avoid z-fighting @@ -1160,7 +1076,7 @@ export default abstract class Layer extends Component< // Call subclass lifecycle method if (context.device instanceof WebGLDevice) { context.device.withParametersWebGL(parameters, () => { - const opts = {renderPass, moduleParameters, uniforms, parameters, context}; + const opts = {renderPass, shaderModuleProps, uniforms, parameters, context}; // extensions for (const extension of this.props.extensions) { @@ -1170,7 +1086,7 @@ export default abstract class Layer extends Component< this.draw(opts); }); } else { - const opts = {renderPass, moduleParameters, uniforms, parameters, context}; + const opts = {renderPass, shaderModuleProps, uniforms, parameters, context}; // extensions for (const extension of this.props.extensions) { diff --git a/modules/core/src/passes/layers-pass.ts b/modules/core/src/passes/layers-pass.ts index 9ddc98fa618..816a1705337 100644 --- a/modules/core/src/passes/layers-pass.ts +++ b/modules/core/src/passes/layers-pass.ts @@ -10,6 +10,8 @@ import type Viewport from '../viewports/viewport'; import type View from '../views/view'; import type Layer from '../lib/layer'; import type {Effect} from '../lib/effect'; +import type {ProjectProps} from '../shaderlib/project/viewport-uniforms'; +import type {PickingProps} from '@luma.gl/shadertools'; export type Rect = {x: number; y: number; width: number; height: number}; @@ -31,7 +33,7 @@ export type LayersPassRenderOptions = { colorMask?: number; scissorRect?: number[]; layerFilter?: ((context: FilterContext) => boolean) | null; - moduleParameters?: any; + shaderModuleProps?: any; /** Stores returned results from Effect.preRender, for use downstream in the render pipeline */ preRenderStats?: Record; }; @@ -39,7 +41,7 @@ export type LayersPassRenderOptions = { type DrawLayerParameters = { shouldDrawLayer: boolean; layerRenderIndex?: number; - moduleParameters?: any; + shaderModuleProps?: any; layerParameters?: any; }; @@ -100,7 +102,7 @@ export default class LayersPass extends Pass { private _drawLayers(renderPass: RenderPass, options: LayersPassRenderOptions) { const { target, - moduleParameters, + shaderModuleProps, viewports, views, onViewportActive, @@ -129,7 +131,7 @@ export default class LayersPass extends Pass { renderPass, { target, - moduleParameters, + shaderModuleProps, viewport: subViewport, view, pass: options.pass, @@ -155,7 +157,7 @@ export default class LayersPass extends Pass { layerFilter, cullRect, effects, - moduleParameters + shaderModuleProps }: LayersPassRenderOptions, /** Internal flag, true if only used to determine whether each layer should be drawn */ evaluateShouldDrawOnly: boolean = false @@ -190,11 +192,11 @@ export default class LayersPass extends Pass { // It can be the same as another layer layerParam.layerRenderIndex = indexResolver(layer, shouldDrawLayer); - layerParam.moduleParameters = this._getModuleParameters( + layerParam.shaderModuleProps = this._getShaderModuleProps( layer, effects, pass, - moduleParameters + shaderModuleProps ); layerParam.layerParameters = { ...layer.context.deck?.props.parameters, @@ -212,11 +214,11 @@ export default class LayersPass extends Pass { /* eslint-disable max-depth, max-statements */ private _drawLayersInViewport( renderPass: RenderPass, - {layers, moduleParameters: globalModuleParameters, pass, target, viewport, view}, + {layers, shaderModuleProps: globalModuleParameters, pass, target, viewport, view}, drawLayerParams ): RenderStats { const glViewport = getGLViewport(this.device, { - moduleParameters: globalModuleParameters, + shaderModuleProps: globalModuleParameters, target, viewport }); @@ -246,7 +248,7 @@ export default class LayersPass extends Pass { // render layers in normal colors for (let layerIndex = 0; layerIndex < layers.length; layerIndex++) { const layer = layers[layerIndex] as Layer; - const {shouldDrawLayer, layerRenderIndex, moduleParameters, layerParameters} = + const {shouldDrawLayer, layerRenderIndex, shaderModuleProps, layerParameters} = drawLayerParams[layerIndex]; // Calculate stats @@ -263,7 +265,9 @@ export default class LayersPass extends Pass { this._lastRenderIndex = Math.max(this._lastRenderIndex, layerRenderIndex); // overwrite layer.context.viewport with the sub viewport - moduleParameters.viewport = viewport; + if (shaderModuleProps.project) { + shaderModuleProps.project.viewport = viewport; + } // TODO v9 - we are sending renderPass both as a parameter and through the context. // Long-term, it is likely better not to have user defined layer methods have to access @@ -273,7 +277,7 @@ export default class LayersPass extends Pass { try { layer._drawLayer({ renderPass, - moduleParameters, + shaderModuleProps, uniforms: {layerIndex: layerRenderIndex}, parameters: layerParameters }); @@ -292,7 +296,11 @@ export default class LayersPass extends Pass { return true; } - protected getModuleParameters(layer: Layer, effects?: Effect[]): any { + protected getShaderModuleProps( + layer: Layer, + effects: Effect[] | undefined, + otherShaderModuleProps: Record + ): any { return null; } @@ -341,7 +349,7 @@ export default class LayersPass extends Pass { return true; } - private _getModuleParameters( + private _getShaderModuleProps( layer: Layer, effects: Effect[] | undefined, pass: string, @@ -349,27 +357,37 @@ export default class LayersPass extends Pass { ): any { // @ts-expect-error TODO - assuming WebGL context const devicePixelRatio = this.device.canvasContext.cssToDeviceRatio(); - - const moduleParameters = Object.assign( - Object.create(layer.internalState?.propsInTransition || layer.props), - { - autoWrapLongitude: layer.wrapLongitude, + const layerProps = layer.internalState?.propsInTransition || layer.props; + + const shaderModuleProps = { + layer: layerProps, + picking: { + isActive: false + } satisfies PickingProps, + project: { viewport: layer.context.viewport, - mousePosition: layer.context.mousePosition, - picking: { - isActive: 0 - }, - devicePixelRatio - } - ); + devicePixelRatio, + modelMatrix: layerProps.modelMatrix, + coordinateSystem: layerProps.coordinateSystem, + coordinateOrigin: layerProps.coordinateOrigin, + autoWrapLongitude: layer.wrapLongitude + } satisfies ProjectProps + }; if (effects) { for (const effect of effects) { - Object.assign(moduleParameters, effect.getModuleParameters?.(layer)); + mergeModuleParameters( + shaderModuleProps, + effect.getShaderModuleProps?.(layer, shaderModuleProps) + ); } } - return Object.assign(moduleParameters, this.getModuleParameters(layer, effects), overrides); + return mergeModuleParameters( + shaderModuleProps, + this.getShaderModuleProps(layer, effects, shaderModuleProps), + overrides + ); } } @@ -425,17 +443,17 @@ export function layerIndexResolver( function getGLViewport( device: Device, { - moduleParameters, + shaderModuleProps, target, viewport }: { - moduleParameters: any; + shaderModuleProps: any; target?: Framebuffer; viewport: Viewport; } ): [number, number, number, number] { const pixelRatio = - (moduleParameters && moduleParameters.devicePixelRatio) || + shaderModuleProps?.project?.devicePixelRatio ?? // @ts-expect-error TODO - assuming WebGL context device.canvasContext.cssToDeviceRatio(); @@ -453,3 +471,21 @@ function getGLViewport( dimensions.height * pixelRatio ]; } + +function mergeModuleParameters( + target: Record, + ...sources: Record[] +): Record { + for (const source of sources) { + if (source) { + for (const key in source) { + if (target[key]) { + Object.assign(target[key], source[key]); + } else { + target[key] = source[key]; + } + } + } + } + return target; +} diff --git a/modules/core/src/passes/pick-layers-pass.ts b/modules/core/src/passes/pick-layers-pass.ts index 940564413dd..a2802840bb5 100644 --- a/modules/core/src/passes/pick-layers-pass.ts +++ b/modules/core/src/passes/pick-layers-pass.ts @@ -6,6 +6,7 @@ import LayersPass, {LayersPassRenderOptions, RenderStats, Rect} from './layers-p import type {Framebuffer, RenderPipelineParameters} from '@luma.gl/core'; import log from '../utils/log'; +import type {Effect} from '../lib/effect'; import type Viewport from '../viewports/viewport'; import type Layer from '../lib/layer'; @@ -69,7 +70,7 @@ export default class PickLayersPass extends LayersPass { effects, pass = 'picking', pickZ, - moduleParameters + shaderModuleProps }: PickLayersPassRenderOptions): { decodePickingColor: PickingColorDecoder | null; stats: RenderStats; @@ -94,7 +95,7 @@ export default class PickLayersPass extends LayersPass { effects: effects?.filter(e => e.useInPicking), pass, isPicking: true, - moduleParameters, + shaderModuleProps, clearColor: [0, 0, 0, 0], colorMask: 0xf, scissorRect @@ -115,13 +116,17 @@ export default class PickLayersPass extends LayersPass { ); } - protected getModuleParameters() { + protected getShaderModuleProps( + layer: Layer, + effects: Effect[] | undefined, + otherShaderModuleProps: Record + ): any { return { picking: { isActive: 1, isAttribute: this.pickZ }, - lightSources: {enabled: false} + lighting: {enabled: false} }; } diff --git a/modules/core/src/passes/shadow-pass.ts b/modules/core/src/passes/shadow-pass.ts index 3ab64599e21..d560b859231 100644 --- a/modules/core/src/passes/shadow-pass.ts +++ b/modules/core/src/passes/shadow-pass.ts @@ -85,9 +85,12 @@ export default class ShadowPass extends LayersPass { return layer.props.shadowEnabled !== false; } - getModuleParameters() { + getShaderModuleProps(layer: Layer, effects: any, otherShaderModuleProps: Record) { return { - drawToShadowMap: true + shadow: { + project: otherShaderModuleProps.project, + drawToShadowMap: true + } }; } } diff --git a/modules/core/src/shaderlib/index.ts b/modules/core/src/shaderlib/index.ts index d1e3279cc80..85c7d67a2fc 100644 --- a/modules/core/src/shaderlib/index.ts +++ b/modules/core/src/shaderlib/index.ts @@ -37,7 +37,7 @@ export function getShaderAssembler() { export {layerUniforms, picking, project, project32, gouraudLighting, phongLighting, shadow}; // Useful for custom shader modules -export type {ProjectUniforms} from './project/viewport-uniforms'; +export type {ProjectProps, ProjectUniforms} from './project/viewport-uniforms'; // TODO - these should be imported from luma.gl /* eslint-disable camelcase */ diff --git a/modules/core/src/shaderlib/misc/layer-uniforms.ts b/modules/core/src/shaderlib/misc/layer-uniforms.ts index 0723bb42305..b6a2080d4f8 100644 --- a/modules/core/src/shaderlib/misc/layer-uniforms.ts +++ b/modules/core/src/shaderlib/misc/layer-uniforms.ts @@ -3,6 +3,7 @@ // Copyright (c) vis.gl contributors import type {ShaderModule} from '@luma.gl/shadertools'; +import type {LayerProps} from '../../types/layer-props'; const uniformBlock = `\ uniform layerUniforms { @@ -10,7 +11,7 @@ uniform layerUniforms { } layer; `; -export type LayerProps = { +export type LayerUniforms = { opacity?: number; }; @@ -18,7 +19,14 @@ export const layerUniforms = { name: 'layer', vs: uniformBlock, fs: uniformBlock, + getUniforms: (props: Partial) => { + return { + // apply gamma to opacity to make it visually "linear" + // TODO - v10: use raw opacity? + opacity: Math.pow(props.opacity!, 1 / 2.2) + }; + }, uniformTypes: { opacity: 'f32' } -} as const satisfies ShaderModule; +} as const satisfies ShaderModule; diff --git a/modules/core/src/shaderlib/shadow/shadow.ts b/modules/core/src/shaderlib/shadow/shadow.ts index 92e525d1342..50870010a11 100644 --- a/modules/core/src/shaderlib/shadow/shadow.ts +++ b/modules/core/src/shaderlib/shadow/shadow.ts @@ -12,7 +12,7 @@ import {pixelsToWorld} from '@math.gl/web-mercator'; import type {Texture} from '@luma.gl/core'; import {ShaderModule} from '@luma.gl/shadertools'; import type Viewport from '../../viewports/viewport'; -import type {ProjectUniforms} from '../project/viewport-uniforms'; +import type {ProjectProps, ProjectUniforms} from '../project/viewport-uniforms'; const uniformBlock = /* glsl */ ` uniform shadowUniforms { @@ -114,8 +114,8 @@ const getMemoizedViewProjectionMatrices = memoize(getViewProjectionMatrices); 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 ShadowModuleProps = { - viewport: Viewport; +export type ShadowModuleProps = { + project: ProjectProps; shadowEnabled?: boolean; drawToShadowMap?: boolean; shadowMaps?: Texture[]; @@ -206,34 +206,34 @@ function getViewProjectionMatrices({ // eslint-disable-next-line complexity function createShadowUniforms( - opts: ShadowModuleProps + opts: Partial ): ShadowModuleBindings & ShadowModuleUniforms { - const {shadowEnabled = true} = opts; - if (!shadowEnabled || !opts.shadowMatrices || !opts.shadowMatrices.length) { + const {shadowEnabled = true, project: projectProps} = opts; + if (!shadowEnabled || !projectProps || !opts.shadowMatrices || !opts.shadowMatrices.length) { return { drawShadowMap: false, useShadowMap: false, - shadow_uShadowMap0: opts.dummyShadowMap, - shadow_uShadowMap1: opts.dummyShadowMap + shadow_uShadowMap0: opts.dummyShadowMap!, + shadow_uShadowMap1: opts.dummyShadowMap! }; } - const projectUniforms = project.getUniforms(opts) as ProjectUniforms; + const projectUniforms = project.getUniforms(projectProps) as ProjectUniforms; const center = getMemoizedViewportCenterPosition({ - viewport: opts.viewport, + viewport: projectProps.viewport, center: projectUniforms.center }); const projectCenters: NumericArray[] = []; const viewProjectionMatrices = getMemoizedViewProjectionMatrices({ shadowMatrices: opts.shadowMatrices, - viewport: opts.viewport + viewport: projectProps.viewport }).slice(); for (let i = 0; i < opts.shadowMatrices.length; i++) { const viewProjectionMatrix = viewProjectionMatrices[i]; const viewProjectionMatrixCentered = viewProjectionMatrix .clone() - .translate(new Vector3(opts.viewport.center).negate()); + .translate(new Vector3(projectProps.viewport.center).negate()); if ( projectUniforms.coordinateSystem === COORDINATE_SYSTEM.LNGLAT && @@ -249,14 +249,14 @@ function createShadowUniforms( } } - const uniforms = { + const uniforms: ShadowModuleUniforms & ShadowModuleBindings = { 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 + shadow_uShadowMap0: opts.dummyShadowMap!, + shadow_uShadowMap1: opts.dummyShadowMap! }; for (let i = 0; i < viewProjectionMatrices.length; i++) { @@ -284,19 +284,7 @@ export default { color = shadow_filterShadowColor(color); ` }, - getUniforms: ( - opts: {drawToShadowMap?: boolean; shadowMaps?: unknown[]} = {}, - context: any = {} - ) => { - if ( - 'viewport' in opts && - (opts.drawToShadowMap || (opts.shadowMaps && opts.shadowMaps.length > 0)) - ) { - // @ts-expect-error if opts.viewport is defined, context should contain the project module's uniforms - return createShadowUniforms(opts, context); - } - return {}; - }, + getUniforms: createShadowUniforms, uniformTypes: { drawShadowMap: 'f32', useShadowMap: 'f32', diff --git a/modules/extensions/src/brushing/brushing-extension.ts b/modules/extensions/src/brushing/brushing-extension.ts index 7d7a5c25033..98b783637d9 100644 --- a/modules/extensions/src/brushing/brushing-extension.ts +++ b/modules/extensions/src/brushing/brushing-extension.ts @@ -88,7 +88,7 @@ export default class BrushingExtension extends LayerExtension { draw(this: Layer, params: any, extension: this) { const {viewport, mousePosition} = params.context; - const {brushingEnabled, brushingRadius, brushingTarget} = params.moduleParameters; + const {brushingEnabled, brushingRadius, brushingTarget} = this.props; const brushingProps: BrushingModuleProps = { viewport, mousePosition, diff --git a/modules/extensions/src/collision-filter/collision-filter-effect.ts b/modules/extensions/src/collision-filter/collision-filter-effect.ts index 6153ca822f5..742dc6860f6 100644 --- a/modules/extensions/src/collision-filter/collision-filter-effect.ts +++ b/modules/extensions/src/collision-filter/collision-filter-effect.ts @@ -10,10 +10,8 @@ import CollisionFilterPass from './collision-filter-pass'; import {MaskPreRenderStats} from '../mask/mask-effect'; // import {debugFBO} from '../utils/debug'; -type CollisionFilterExtensionProps = { - collisionTestProps?: {}; - collisionGroup: string; -}; +import type {CollisionFilterExtensionProps} from './collision-filter-extension'; +import type {CollisionModuleProps} from './shader-module'; // Factor by which to downscale Collision FBO relative to canvas const DOWNSCALE = 2; @@ -159,11 +157,16 @@ export default class CollisionFilterEffect implements Effect { viewports: viewport ? [viewport] : [], onViewportActive, views, - moduleParameters: { - // To avoid feedback loop forming between Framebuffer and active Texture. - dummyCollisionMap: this.dummyCollisionMap, - // @ts-expect-error TODO - assuming WebGL context - devicePixelRatio: collisionFBO.device.canvasContext.getDevicePixelRatio() / DOWNSCALE + shaderModuleProps: { + collision: { + enabled: true, + // To avoid feedback loop forming between Framebuffer and active Texture. + dummyCollisionMap: this.dummyCollisionMap + }, + project: { + // @ts-expect-error TODO - assuming WebGL context + devicePixelRatio: collisionFBO.device.canvasContext.getDevicePixelRatio() / DOWNSCALE + } } }); } @@ -179,7 +182,7 @@ export default class CollisionFilterEffect implements Effect { ): Record { const channelMap = {}; for (const layer of collisionLayers) { - const {collisionGroup} = layer.props; + const collisionGroup = layer.props.collisionGroup!; let channelInfo = channelMap[collisionGroup]; if (!channelInfo) { channelInfo = {collisionGroup, layers: [], layerBounds: [], allLayersLoaded: true}; @@ -210,13 +213,21 @@ export default class CollisionFilterEffect implements Effect { return channelMap; } - getModuleParameters(layer: Layer): { - collisionFBO: Framebuffer; - dummyCollisionMap: Texture; + getShaderModuleProps(layer: Layer): { + collision: CollisionModuleProps; } { - const {collisionGroup} = (layer as Layer).props; + const {collisionGroup, collisionEnabled} = (layer as Layer) + .props; const {collisionFBOs, dummyCollisionMap} = this; - return {collisionFBO: collisionFBOs[collisionGroup], dummyCollisionMap: dummyCollisionMap!}; + const collisionFBO = collisionFBOs[collisionGroup!]; + const enabled = collisionEnabled && Boolean(collisionFBO); + return { + collision: { + enabled, + collisionFBO, + dummyCollisionMap: dummyCollisionMap! + } + }; } cleanup(): void { diff --git a/modules/extensions/src/collision-filter/collision-filter-extension.ts b/modules/extensions/src/collision-filter/collision-filter-extension.ts index d29a8011f26..9c4d3c2112f 100644 --- a/modules/extensions/src/collision-filter/collision-filter-extension.ts +++ b/modules/extensions/src/collision-filter/collision-filter-extension.ts @@ -3,7 +3,7 @@ // Copyright (c) vis.gl contributors import {Accessor, Layer, LayerContext, LayerExtension} from '@deck.gl/core'; -import collision, {CollisionModuleProps} from './shader-module'; +import collision from './shader-module'; import CollisionFilterEffect from './collision-filter-effect'; const defaultProps = { @@ -46,24 +46,12 @@ export default class CollisionFilterExtension extends LayerExtension { } /* eslint-disable camelcase */ - draw(this: Layer, {moduleParameters}: any) { - const {collisionEnabled} = this.props; - const {collisionFBO, drawToCollisionMap, dummyCollisionMap} = moduleParameters; - const enabled = collisionEnabled && Boolean(collisionFBO); - - if (drawToCollisionMap) { + draw(this: Layer, {shaderModuleProps}: any) { + if (shaderModuleProps.collision?.drawToCollisionMap) { // Override any props with those defined in collisionTestProps // @ts-ignore this.props = this.clone(this.props.collisionTestProps).props; } - - const collisionProps: CollisionModuleProps = { - enabled, - collisionFBO, - drawToCollisionMap, - dummyCollisionMap - }; - this.setShaderModuleProps({collision: collisionProps}); } initializeState( diff --git a/modules/extensions/src/collision-filter/collision-filter-pass.ts b/modules/extensions/src/collision-filter/collision-filter-pass.ts index 9ccdf667c1d..0b4dcf6f7b7 100644 --- a/modules/extensions/src/collision-filter/collision-filter-pass.ts +++ b/modules/extensions/src/collision-filter/collision-filter-pass.ts @@ -20,15 +20,17 @@ export default class CollisionFilterPass extends LayersPass { return {...layer.props.parameters, blend: false, depthRange: [0, 1], depthTest: true}; } - getModuleParameters() { + getShaderModuleProps() { // Draw picking colors into collision FBO return { - drawToCollisionMap: true, + collision: { + drawToCollisionMap: true + }, picking: { isActive: 1, isAttribute: false }, - lightSources: {enabled: false} + lighting: {enabled: false} }; } } diff --git a/modules/extensions/src/collision-filter/shader-module.ts b/modules/extensions/src/collision-filter/shader-module.ts index 77a9a7c680b..39346781e0a 100644 --- a/modules/extensions/src/collision-filter/shader-module.ts +++ b/modules/extensions/src/collision-filter/shader-module.ts @@ -106,7 +106,7 @@ const getCollisionUniforms = ( } const {enabled, collisionFBO, drawToCollisionMap, dummyCollisionMap} = opts; return { - enabled, + enabled: enabled && !drawToCollisionMap, sort: Boolean(drawToCollisionMap), collision_texture: !drawToCollisionMap && collisionFBO ? collisionFBO.colorAttachments[0] : dummyCollisionMap diff --git a/modules/extensions/src/data-filter/data-filter-extension.ts b/modules/extensions/src/data-filter/data-filter-extension.ts index 27921ce26bc..f7a93676c91 100644 --- a/modules/extensions/src/data-filter/data-filter-extension.ts +++ b/modules/extensions/src/data-filter/data-filter-extension.ts @@ -266,13 +266,12 @@ export default class DataFilterExtension extends LayerExtension< const filterModel = this.state.filterModel as Model; const filterNeedsUpdate = this.state.filterNeedsUpdate as boolean; - const {onFilteredItemsChange} = this.props; - if (!this.state.categoryBitMask) { extension._updateCategoryBitMask.call(this, params, extension); } const { + onFilteredItemsChange, extensions, filterEnabled, filterRange, @@ -280,7 +279,7 @@ export default class DataFilterExtension extends LayerExtension< filterTransformSize, filterTransformColor, filterCategories - } = params.moduleParameters; + } = this.props; const dataFilterProps: DataFilterModuleProps = { extensions, filterEnabled, diff --git a/modules/extensions/src/fill-style/fill-style-extension.ts b/modules/extensions/src/fill-style/fill-style-extension.ts index 2207e492ca0..1df03e11f0b 100644 --- a/modules/extensions/src/fill-style/fill-style-extension.ts +++ b/modules/extensions/src/fill-style/fill-style-extension.ts @@ -159,11 +159,9 @@ export default class FillStyleExtension extends LayerExtension | null; + getShaderModuleProps(): { + mask: { + maskMap: Texture; + maskChannels: Record | null; + }; } { return { - maskMap: this.masks ? this.maskMap! : this.dummyMaskMap!, - maskChannels: this.masks + mask: { + maskMap: this.masks ? this.maskMap! : this.dummyMaskMap!, + maskChannels: this.masks + } }; } diff --git a/modules/extensions/src/mask/mask-extension.ts b/modules/extensions/src/mask/mask-extension.ts index b42416d7182..ea3742e064e 100644 --- a/modules/extensions/src/mask/mask-extension.ts +++ b/modules/extensions/src/mask/mask-extension.ts @@ -53,11 +53,11 @@ export default class MaskExtension extends LayerExtension { } /* eslint-disable camelcase */ - draw(this: Layer>, {context, moduleParameters}: any) { + draw(this: Layer>, {context, shaderModuleProps}: any) { const maskProps = {} as MaskProps; maskProps.maskByInstance = Boolean(this.state.maskByInstance); const {maskId, maskInverted} = this.props; - const {maskChannels} = moduleParameters; + const {maskChannels} = shaderModuleProps.mask || {}; const {viewport} = context; if (maskChannels && maskChannels[maskId]) { const {index, bounds, coordinateOrigin: fromCoordinateOrigin} = maskChannels[maskId]; diff --git a/modules/extensions/src/mask/shader-module.ts b/modules/extensions/src/mask/shader-module.ts index 2283adc8934..df4e4e5b78e 100644 --- a/modules/extensions/src/mask/shader-module.ts +++ b/modules/extensions/src/mask/shader-module.ts @@ -81,7 +81,7 @@ in vec2 mask_texCoords; // Debug: show extent of render target // fragColor = vec4(mask_texCoords, 0.0, 1.0); - fragColor = texture(mask_texture, mask_texCoords); + // fragColor = texture(mask_texture, mask_texCoords); if (!mask) discard; } diff --git a/modules/extensions/src/terrain/shader-module.ts b/modules/extensions/src/terrain/shader-module.ts index f12a7baa978..ed951fc1b35 100644 --- a/modules/extensions/src/terrain/shader-module.ts +++ b/modules/extensions/src/terrain/shader-module.ts @@ -5,7 +5,7 @@ /* eslint-disable camelcase */ import type {ShaderModule} from '@luma.gl/shadertools'; -import {project, ProjectUniforms, Viewport} from '@deck.gl/core'; +import {project, ProjectProps, ProjectUniforms, Viewport} from '@deck.gl/core'; import type {Texture} from '@luma.gl/core'; import type {Bounds} from '../utils/projection-utils'; @@ -13,8 +13,8 @@ import type {TerrainCover} from './terrain-cover'; /** Module parameters expected by the terrain shader module */ export type TerrainModuleProps = { - viewport: Viewport; - picking: {isActive?: boolean}; + project: ProjectProps; + isPicking: boolean; heightMap: Texture | null; heightMapBounds?: Bounds | null; dummyHeightMap: Texture; @@ -129,7 +129,7 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US useTerrainHeightMap, terrainSkipRender } = opts; - const projectUniforms = project.getUniforms(opts) as ProjectUniforms; + const projectUniforms = project.getUniforms(opts.project) as ProjectUniforms; const {commonOrigin} = projectUniforms; let mode: number = terrainSkipRender ? TERRAIN_MODE.SKIP : TERRAIN_MODE.NONE; @@ -146,12 +146,11 @@ if ((terrain.mode == TERRAIN_MODE_USE_COVER) || (terrain.mode == TERRAIN_MODE_US bounds = heightMapBounds!; } else if (terrainCover) { // This is a terrain layer - const isPicking = opts.picking?.isActive; - const fbo = isPicking + const fbo = opts.isPicking ? terrainCover.getPickingFramebuffer() : terrainCover.getRenderFramebuffer(); sampler = fbo?.colorAttachments[0].texture; - if (isPicking) { + if (opts.isPicking) { // Never render the layer itself in picking pass mode = TERRAIN_MODE.SKIP; } diff --git a/modules/extensions/src/terrain/terrain-effect.ts b/modules/extensions/src/terrain/terrain-effect.ts index 44c9381f5ad..2955ebf532a 100644 --- a/modules/extensions/src/terrain/terrain-effect.ts +++ b/modules/extensions/src/terrain/terrain-effect.ts @@ -86,18 +86,23 @@ export class TerrainEffect implements Effect { this._updateTerrainCovers(terrainLayers, drapeLayers, viewport, opts); } - getModuleParameters(layer: Layer): Omit { - const {viewport} = layer.context; + getShaderModuleProps( + layer: Layer, + otherShaderModuleProps: Record + ): {terrain: TerrainModuleProps} { const {terrainDrawMode} = layer.state; return { - viewport, - heightMap: this.heightMap?.getRenderFramebuffer()?.colorAttachments[0].texture || null, - heightMapBounds: this.heightMap?.bounds, - dummyHeightMap: this.dummyHeightMap!, - terrainCover: this.isDrapingEnabled ? this.terrainCovers.get(layer.id) : null, - useTerrainHeightMap: terrainDrawMode === 'offset', - terrainSkipRender: terrainDrawMode === 'drape' || !layer.props.operation.includes('draw') + terrain: { + project: otherShaderModuleProps.project, + isPicking: this.isPicking, + heightMap: this.heightMap?.getRenderFramebuffer()?.colorAttachments[0].texture || null, + heightMapBounds: this.heightMap?.bounds, + dummyHeightMap: this.dummyHeightMap!, + terrainCover: this.isDrapingEnabled ? this.terrainCovers.get(layer.id) : null, + useTerrainHeightMap: terrainDrawMode === 'offset', + terrainSkipRender: terrainDrawMode === 'drape' || !layer.props.operation.includes('draw') + } }; } @@ -134,11 +139,15 @@ export class TerrainEffect implements Effect { this.terrainPass.renderHeightMap(this.heightMap, { ...opts, layers: terrainLayers, - moduleParameters: { - heightMapBounds: this.heightMap.bounds, - dummyHeightMap: this.dummyHeightMap, - devicePixelRatio: 1, - drawToTerrainHeightMap: true + shaderModuleProps: { + terrain: { + heightMapBounds: this.heightMap.bounds, + dummyHeightMap: this.dummyHeightMap, + drawToTerrainHeightMap: true + }, + project: { + devicePixelRatio: 1 + } } }); } @@ -192,10 +201,14 @@ export class TerrainEffect implements Effect { renderPass.renderTerrainCover(terrainCover, { ...opts, layers: drapeLayers, - moduleParameters: { - dummyHeightMap: this.dummyHeightMap, - terrainSkipRender: false, - devicePixelRatio: 1 + shaderModuleProps: { + terrain: { + dummyHeightMap: this.dummyHeightMap, + terrainSkipRender: false + }, + project: { + devicePixelRatio: 1 + } } }); diff --git a/modules/extensions/src/terrain/terrain-extension.ts b/modules/extensions/src/terrain/terrain-extension.ts index 95c6bcd5e5e..d08e09d0cbf 100644 --- a/modules/extensions/src/terrain/terrain-extension.ts +++ b/modules/extensions/src/terrain/terrain-extension.ts @@ -4,7 +4,7 @@ import {LayerExtension, UpdateParameters} from '@deck.gl/core'; import {TerrainEffect} from './terrain-effect'; -import {terrainModule, TerrainModuleProps} from './shader-module'; +import {terrainModule} from './shader-module'; import type {Layer} from '@deck.gl/core'; diff --git a/modules/extensions/src/terrain/terrain-pass.ts b/modules/extensions/src/terrain/terrain-pass.ts index bae47e319d7..da45506dd42 100644 --- a/modules/extensions/src/terrain/terrain-pass.ts +++ b/modules/extensions/src/terrain/terrain-pass.ts @@ -87,4 +87,12 @@ export class TerrainPass extends LayersPass { ...(layer.props.operation.includes('terrain') && TERRAIN_BLENDING) }; } + + getShaderModuleProps(layer: Layer, effects: any, otherShaderModuleProps: Record) { + return { + terrain: { + project: otherShaderModuleProps.project + } + }; + } } diff --git a/modules/extensions/src/terrain/terrain-picking-pass.ts b/modules/extensions/src/terrain/terrain-picking-pass.ts index 3658462742d..4db5f56f46a 100644 --- a/modules/extensions/src/terrain/terrain-picking-pass.ts +++ b/modules/extensions/src/terrain/terrain-picking-pass.ts @@ -82,4 +82,12 @@ export class TerrainPickingPass extends PickLayersPass { } return {...parameters, depthTest: false}; } + + getShaderModuleProps(layer: Layer, effects: any, otherShaderModuleProps: Record) { + return { + terrain: { + project: otherShaderModuleProps.project + } + }; + } } diff --git a/modules/layers/src/bitmap-layer/bitmap-layer.ts b/modules/layers/src/bitmap-layer/bitmap-layer.ts index fd2126ad99a..cb73a39ec01 100644 --- a/modules/layers/src/bitmap-layer/bitmap-layer.ts +++ b/modules/layers/src/bitmap-layer/bitmap-layer.ts @@ -268,11 +268,11 @@ export default class BitmapLayer extends Layer< } draw(opts) { - const {moduleParameters, uniforms} = opts; + const {shaderModuleProps, uniforms} = opts; const {model, coordinateConversion, bounds, disablePicking} = this.state; const {image, desaturate, transparentColor, tintColor} = this.props; - if (moduleParameters.picking.isActive && disablePicking) { + if (shaderModuleProps.picking.isActive && disablePicking) { return; } diff --git a/test/data/grid-aggregation-data.js b/test/data/grid-aggregation-data.js index 8bdbd9e7cd0..dc600b6a8ce 100644 --- a/test/data/grid-aggregation-data.js +++ b/test/data/grid-aggregation-data.js @@ -81,7 +81,7 @@ const fixture = { } }, cellSize: [25, 25], - moduleSettings: {viewport}, + shaderModuleProps: {viewport}, projectPoints: true, translation: [1, -1], scaling: [width / 2, -height / 2, 1], diff --git a/test/modules/aggregation-layers/common/webgl-aggregator.spec.ts b/test/modules/aggregation-layers/common/webgl-aggregator.spec.ts index 9d984477edb..e4b8ee85b03 100644 --- a/test/modules/aggregation-layers/common/webgl-aggregator.spec.ts +++ b/test/modules/aggregation-layers/common/webgl-aggregator.spec.ts @@ -140,7 +140,7 @@ test('WebGLAggregator#1D', t => { }); aggregator.update(); - aggregator.preDraw({moduleSettings: {}}); + aggregator.preDraw(); t.is(aggregator.binCount, 15, 'binCount'); @@ -248,7 +248,7 @@ test('WebGLAggregator#2D', t => { }); aggregator.update(); - aggregator.preDraw({moduleSettings: {}}); + aggregator.preDraw(); t.is(aggregator.binCount, 20, 'binCount'); diff --git a/test/modules/core/effects/lighting-effect.spec.ts b/test/modules/core/effects/lighting-effect.spec.ts index 1dc9c0db671..0fadc130d59 100644 --- a/test/modules/core/effects/lighting-effect.spec.ts +++ b/test/modules/core/effects/lighting-effect.spec.ts @@ -35,7 +35,7 @@ test('LightingEffect#constructor', t => { t.end(); }); -test('LightingEffect#getModuleParameters', t => { +test('LightingEffect#getShaderModuleProps', t => { const cameraLight = new CameraLight(); const pointLight = new PointLight(); const lightingEffect = new LightingEffect({cameraLight, pointLight}); @@ -62,16 +62,16 @@ test('LightingEffect#getModuleParameters', t => { pixelRatio: 1 }); - const {lightSources} = lightingEffect.getModuleParameters(layer); - t.is(lightSources.pointLights.length, 2, 'Lights are exported'); + const {lighting} = lightingEffect.getShaderModuleProps(layer); + t.is(lighting.pointLights.length, 2, 'Lights are exported'); t.ok( - equals(lightSources.pointLights[0].position, [0, 0, 0.018310546875]), + equals(lighting.pointLights[0].position, [0, 0, 0.018310546875]), 'Camera light projection is ok' ); - t.deepEqual(lightSources.pointLights[1].color, [255, 0, 0], 'point light color is ok'); + t.deepEqual(lighting.pointLights[1].color, [255, 0, 0], 'point light color is ok'); - t.equal(lightSources.ambientLight, undefined, 'Lighting effect getGLParameters is ok'); - t.deepEqual(lightSources.directionalLights, [], 'Lighting effect getGLParameters is ok'); + t.equal(lighting.ambientLight, undefined, 'Lighting effect getGLParameters is ok'); + t.deepEqual(lighting.directionalLights, [], 'Lighting effect getGLParameters is ok'); lightingEffect.cleanup(effectContext); layerManager.finalize(); diff --git a/test/modules/core/lib/layer.spec.ts b/test/modules/core/lib/layer.spec.ts index c6e1b20554d..442e11a141a 100644 --- a/test/modules/core/lib/layer.spec.ts +++ b/test/modules/core/lib/layer.spec.ts @@ -449,7 +449,7 @@ test('Layer#uniformTransitions', t => { onAfterUpdate: () => t.deepEquals( drawCalls.pop(), - {opacity: Math.pow(0.5, 1 / 2.2), modelMatrix: scale2Mat4}, + {opacity: 0.5, modelMatrix: scale2Mat4}, 'layer drawn with opacity in transition' ) }, diff --git a/test/modules/core/passes/layers-pass.spec.ts b/test/modules/core/passes/layers-pass.spec.ts index ce6c19e175b..f1229989cfb 100644 --- a/test/modules/core/passes/layers-pass.spec.ts +++ b/test/modules/core/passes/layers-pass.spec.ts @@ -307,8 +307,10 @@ test('LayersPass#GLViewport', t => { name: 'external framebuffer pixel ratio 2', target: framebuffer, viewport: {}, - moduleParameters: { - devicePixelRatio: 2 + shaderModuleProps: { + project: { + devicePixelRatio: 2 + } }, expectedGLViewport: [0, 98, 2, 2] }, @@ -328,20 +330,22 @@ test('LayersPass#GLViewport', t => { name: 'external framebuffer offset pixel ratio 2', target: framebuffer, viewport: {x: 5, y: 10, width: 30, height: 30}, - moduleParameters: { - devicePixelRatio: 2 + shaderModuleProps: { + project: { + devicePixelRatio: 2 + } }, expectedGLViewport: [10, 20, 60, 60] } ]; - for (const {name, target, viewport, moduleParameters, expectedGLViewport} of testCases) { + for (const {name, target, viewport, shaderModuleProps, expectedGLViewport} of testCases) { layersPass.render({ target, viewports: [new Viewport({id: 'A', ...viewport})], layers: layerManager.getLayers(), onViewportActive: layerManager.activateViewport, - moduleParameters, + shaderModuleProps, onError: t.notOk }); diff --git a/test/modules/core/passes/shadow-pass.spec.ts b/test/modules/core/passes/shadow-pass.spec.ts index e648e23c588..d4e1e582b91 100644 --- a/test/modules/core/passes/shadow-pass.spec.ts +++ b/test/modules/core/passes/shadow-pass.spec.ts @@ -56,7 +56,7 @@ test('ShadowPass#render', t => { t.end(); }); -test('ShadowPass#getModuleParameters', t => { +test('ShadowPass#getShaderModuleProps', t => { const layer = new PolygonLayer({ data: FIXTURES.polygons.slice(0, 3), getPolygon: f => f, @@ -64,9 +64,11 @@ test('ShadowPass#getModuleParameters', t => { }); const shadowPass = new ShadowPass(device, {pixelRatio: 1.0}); - const moduleParameters = shadowPass.getModuleParameters(layer); + const shaderModuleProps = shadowPass.getShaderModuleProps(layer, [], { + project: {} + }); - t.equal(moduleParameters.drawToShadowMap, true, `ShadowPass has module parameters`); + t.equal(shaderModuleProps.shadow.drawToShadowMap, true, `ShadowPass has module props`); shadowPass.delete(); t.end(); }); diff --git a/test/modules/core/shaderlib/shadow/shadow.spec.ts b/test/modules/core/shaderlib/shadow/shadow.spec.ts index 582d7a32313..ce581cfe5a4 100644 --- a/test/modules/core/shaderlib/shadow/shadow.spec.ts +++ b/test/modules/core/shaderlib/shadow/shadow.spec.ts @@ -132,7 +132,7 @@ test('shadow#getUniforms', t => { }); let uniforms = shadow.getUniforms({ - viewport, + project: {viewport}, shadowMatrices: [viewMatrix], drawToShadowMap: true, dummyShadowMaps: [true] @@ -157,15 +157,12 @@ test('shadow#getUniforms', t => { // LNGLAT_AUTO_OFFSET mode viewport = TEST_VIEWPORT2; - uniforms = shadow.getUniforms( - { - viewport, - shadowMatrices: [viewMatrix], - drawToShadowMap: true, - dummyShadowMaps: [true] - }, - project.getUniforms({viewport}) - ); + uniforms = shadow.getUniforms({ + project: {viewport}, + shadowMatrices: [viewMatrix], + drawToShadowMap: true, + dummyShadowMaps: [true] + }); for (const value of TEST_CASE2) { const result = uniforms.viewProjectionMatrix0.transform(value.xyz); @@ -184,18 +181,15 @@ test('shadow#getUniforms', t => { // Non-Geospatial Identity Mode viewport = TEST_VIEWPORT3; - uniforms = shadow.getUniforms( - { + uniforms = shadow.getUniforms({ + project: { viewport, - shadowMatrices: [viewMatrix], - drawToShadowMap: true, - dummyShadowMaps: [true] - }, - { - center: [0, 0, 0, 0], coordinateSystem: COORDINATE_SYSTEM.CARTESIAN - } - ); + }, + shadowMatrices: [viewMatrix], + drawToShadowMap: true, + dummyShadowMaps: [true] + }); for (const value of TEST_CASE3) { const result = uniforms.viewProjectionMatrix0.transform(value.xyz); diff --git a/test/modules/extensions/collision-filter/collision-filter-effect.spec.ts b/test/modules/extensions/collision-filter/collision-filter-effect.spec.ts index 3635178d6d6..a634c609633 100644 --- a/test/modules/extensions/collision-filter/collision-filter-effect.spec.ts +++ b/test/modules/extensions/collision-filter/collision-filter-effect.spec.ts @@ -117,20 +117,20 @@ test('CollisionFilterEffect#update', t => { }; preRenderWithLayers([TEST_LAYER], 'Initial render'); - let parameters = collisionFilterEffect.getModuleParameters(TEST_LAYER); + let parameters = collisionFilterEffect.getShaderModuleProps(TEST_LAYER).collision; t.ok(parameters.collisionFBO, 'collision map is in parameters'); t.ok(parameters.dummyCollisionMap, 'dummy collision map is in parameters'); preRenderWithLayers([TEST_LAYER, TEST_LAYER_2], 'Add second collision layer'); - parameters = collisionFilterEffect.getModuleParameters(TEST_LAYER); + parameters = collisionFilterEffect.getShaderModuleProps(TEST_LAYER).collision; t.ok(parameters.collisionFBO, 'collision map is in parameters'); t.ok(parameters.dummyCollisionMap, 'dummy collision map is in parameters'); - parameters = collisionFilterEffect.getModuleParameters(TEST_LAYER_2); + parameters = collisionFilterEffect.getShaderModuleProps(TEST_LAYER_2).collision; t.ok(parameters.collisionFBO, 'collision map is in parameters'); t.ok(parameters.dummyCollisionMap, 'dummy collision map is in parameters'); preRenderWithLayers([TEST_LAYER_2], 'Remove first layer'); - parameters = collisionFilterEffect.getModuleParameters(TEST_LAYER_2); + parameters = collisionFilterEffect.getShaderModuleProps(TEST_LAYER_2).collision; t.ok(parameters.collisionFBO, 'collision map is in parameters'); t.ok(parameters.dummyCollisionMap, 'dummy collision map is in parameters'); @@ -138,10 +138,10 @@ test('CollisionFilterEffect#update', t => { [TEST_LAYER_2, TEST_LAYER_DIFFERENT_GROUP], 'Add layer with different collision group' ); - parameters = collisionFilterEffect.getModuleParameters(TEST_LAYER_2); + parameters = collisionFilterEffect.getShaderModuleProps(TEST_LAYER_2).collision; t.ok(parameters.collisionFBO, 'collision map is in parameters'); t.ok(parameters.dummyCollisionMap, 'dummy collision map is in parameters'); - parameters = collisionFilterEffect.getModuleParameters(TEST_LAYER_DIFFERENT_GROUP); + parameters = collisionFilterEffect.getShaderModuleProps(TEST_LAYER_DIFFERENT_GROUP).collision; t.ok(parameters.collisionFBO, 'collision map is in parameters'); t.ok(parameters.dummyCollisionMap, 'dummy collision map is in parameters'); diff --git a/test/modules/extensions/collision-filter/collision-filter-pass.spec.ts b/test/modules/extensions/collision-filter/collision-filter-pass.spec.ts index 5eb25354b36..87342d7951c 100644 --- a/test/modules/extensions/collision-filter/collision-filter-pass.spec.ts +++ b/test/modules/extensions/collision-filter/collision-filter-pass.spec.ts @@ -7,27 +7,27 @@ import test from 'tape-promise/tape'; import CollisionFilterPass from '@deck.gl/extensions/collision-filter/collision-filter-pass'; import {device} from '@deck.gl/test-utils'; -test('CollisionFilterPass#getModuleParameters', t => { +test('CollisionFilterPass#getShaderModuleProps', t => { const collisionFilterPass = new CollisionFilterPass(device); - const moduleParameters = collisionFilterPass.getModuleParameters(); + const shaderModuleProps = collisionFilterPass.getShaderModuleProps(); t.equal( - moduleParameters.drawToCollisionMap, + shaderModuleProps.collision.drawToCollisionMap, true, `CollisionFilterPass has drawToCollisionMap module parameter` ); t.equal( - moduleParameters.picking.isActive, + shaderModuleProps.picking.isActive, 1, `CollisionFilterPass has picking.isActive module parameter` ); t.equal( - moduleParameters.picking.isAttribute, + shaderModuleProps.picking.isAttribute, false, `CollisionFilterPass has picking.isAttribute module parameter` ); t.deepEqual( - moduleParameters.lightSources, + shaderModuleProps.lighting, {enabled: false}, `CollisionFilterPass disables lighting module` ); diff --git a/test/modules/extensions/mask/mask-effect.spec.ts b/test/modules/extensions/mask/mask-effect.spec.ts index 0a2ee55673b..08e7b4ccc42 100644 --- a/test/modules/extensions/mask/mask-effect.spec.ts +++ b/test/modules/extensions/mask/mask-effect.spec.ts @@ -95,7 +95,7 @@ test('MaskEffect#update', t => { preRenderWithLayers([TEST_MASK_LAYER, TEST_LAYER], 'Initial render'); - let parameters = maskEffect.getModuleParameters(TEST_LAYER); + let parameters = maskEffect.getShaderModuleProps(TEST_LAYER).mask; t.is(parameters.maskMap, maskEffect.maskMap, 'Mask map is in parameters'); let mask = parameters.maskChannels['test-mask-layer']; t.is(mask?.index, 0, 'Mask is rendered in channel 0'); @@ -104,7 +104,7 @@ test('MaskEffect#update', t => { preRenderWithLayers([TEST_MASK_LAYER, TEST_LAYER, TEST_MASK_LAYER2], 'Add second mask'); - parameters = maskEffect.getModuleParameters(TEST_LAYER); + parameters = maskEffect.getShaderModuleProps(TEST_LAYER).mask; mask = parameters.maskChannels['test-mask-layer']; t.is(mask?.index, 0, 'Mask is rendered in channel 0'); t.is(mask?.bounds, bounds, 'Using cached mask bounds'); @@ -115,7 +115,7 @@ test('MaskEffect#update', t => { preRenderWithLayers([TEST_LAYER, TEST_MASK_LAYER2], 'Remove first mask'); - parameters = maskEffect.getModuleParameters(TEST_LAYER); + parameters = maskEffect.getShaderModuleProps(TEST_LAYER).mask; mask = parameters.maskChannels['test-mask-layer']; t.notOk(mask, 'Mask is removed'); mask = parameters.maskChannels['test-mask-layer-2']; @@ -127,7 +127,7 @@ test('MaskEffect#update', t => { 'Update second mask, add third' ); - parameters = maskEffect.getModuleParameters(TEST_LAYER); + parameters = maskEffect.getShaderModuleProps(TEST_LAYER).mask; mask = parameters.maskChannels['test-mask-layer-2']; t.is(mask?.index, 1, 'Second mask is rendered in channel 1'); t.not(mask?.bounds, bounds, 'Second mask is updated'); @@ -165,14 +165,14 @@ test('MaskEffect#coordinates', t => { preRenderWithLayers([TEST_MASK_LAYER, TEST_LAYER], 'Initial render'); - let parameters = maskEffect.getModuleParameters(TEST_LAYER); + let parameters = maskEffect.getShaderModuleProps(TEST_LAYER).mask; let mask = parameters.maskChannels['test-mask-layer']; t.same(mask?.coordinateOrigin, [0, 0, 0], 'Mask has correct coordinate origin'); t.is(mask?.coordinateSystem, COORDINATE_SYSTEM.DEFAULT, 'Mask has correct coordinate system'); preRenderWithLayers([TEST_MASK_LAYER_CARTESIAN, TEST_LAYER], 'Update to cartesion coordinates'); - parameters = maskEffect.getModuleParameters(TEST_LAYER); + parameters = maskEffect.getShaderModuleProps(TEST_LAYER).mask; mask = parameters.maskChannels['test-mask-layer']; t.same(mask?.coordinateOrigin, [1, 2, 3], 'Mask has correct coordinate origin'); t.is(mask?.coordinateSystem, COORDINATE_SYSTEM.CARTESIAN, 'Mask has correct coordinate system');