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

Generic module props handling in Layer class #9192

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/api-reference/aggregation-layers/aggregator.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
9 changes: 6 additions & 3 deletions modules/aggregation-layers/src/common/aggregation-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type WebGLAggregationProps = AggregationProps & {
*/
binIdRange: [start: number, end: number][];
/** Context props passed to the shader modules */
moduleSettings?: ModelProps['moduleSettings'];
shaderModuleProps?: Record<string, any>;
};

/** An Aggregator implementation that calculates aggregation on the GPU */
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,9 @@ export class WebGLBinSorter {
}

setModelProps(
props: Pick<
ModelProps,
'moduleSettings' | 'vertexCount' | 'uniforms' | 'attributes' | 'constantAttributes'
>
props: Pick<ModelProps, 'vertexCount' | 'uniforms' | 'attributes' | 'constantAttributes'> & {
shaderModuleProps?: Record<string, any>;
}
) {
const model = this.model;
if (props.attributes) {
Expand All @@ -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);
}
}

Expand Down
4 changes: 2 additions & 2 deletions modules/aggregation-layers/src/contour-layer/contour-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,8 @@ export default class GridLayer<DataT = any, ExtraPropsT extends {} = {}> 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;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Better to clone the project object to avoid mutating it in the calling code?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The project object is soft referenced by other dependent modules (shadow, terrain, etc.)

}
super.draw(opts);
}
Expand Down
4 changes: 2 additions & 2 deletions modules/aggregation-layers/src/grid-layer/grid-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,8 @@ export default class GridLayer<DataT = any, ExtraPropsT extends {} = {}> 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions modules/aggregation-layers/src/hexagon-layer/hexagon-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
11 changes: 6 additions & 5 deletions modules/carto/src/layers/post-process-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -134,10 +134,11 @@ export function PostProcessModifier<T extends Constructor<DrawableCompositeLayer

_resizeBuffers(this: PostProcessLayer, opts: any) {
// TODO we could likely render to a smaller buffer for better perf
const {moduleParameters} = opts;
const {shaderModuleProps} = opts;
const {viewport} = this.context;
const width = moduleParameters.devicePixelRatio * viewport.width;
const height = moduleParameters.devicePixelRatio * viewport.height;
const {devicePixelRatio} = shaderModuleProps.project;
const width = devicePixelRatio * viewport.width;
const height = devicePixelRatio * viewport.height;
this.internalState.renderBuffers.forEach((fbo: Framebuffer) => fbo.resize({width, height}));
}

Expand Down
43 changes: 24 additions & 19 deletions modules/core/src/effects/lighting/lighting-effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down Expand Up @@ -117,43 +118,47 @@ export default class LightingEffect implements Effect {
viewports,
onViewportActive,
views,
moduleParameters: {
shadowLightId: i,
dummyShadowMap: this.dummyShadowMap,
shadowMatrices: this.shadowMatrices
shaderModuleProps: {
shadow: {
Pessimistress marked this conversation as resolved.
Show resolved Hide resolved
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<string, any>) {
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 =>
directionalLight.getProjectedLight({layer})
),
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 {
Expand Down
2 changes: 1 addition & 1 deletion modules/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion modules/core/src/lib/effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, any>): any;

// / Lifecycle methods
/** Called when this effect is added */
Expand Down
Loading
Loading