Skip to content

Commit

Permalink
Lighting UBO (#9074)
Browse files Browse the repository at this point in the history
  • Loading branch information
felixpalmer authored Aug 19, 2024
1 parent 5a90f5f commit e101223
Show file tree
Hide file tree
Showing 33 changed files with 167 additions and 154 deletions.
8 changes: 7 additions & 1 deletion docs/api-reference/core/point-light.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PointLight

Create a point light source which emits from a point in all directions.Point lights attenuation is not available. At most 5 directional lights can be supported.
Create a point light source which emits from a point in all directions. At most 5 directional lights can be supported.

<div align="center">
<div>
Expand Down Expand Up @@ -33,6 +33,12 @@ const pointLight = new PointLight({color, intensity, position});
* `color` - (number[3],) RGB color of point light source, default value is `[255, 255, 255]`.
* `intensity` - (number) Strength of point light source, default value is `1.0`.
* `position` - (number[3]) Location of point light source, default value is `[0, 0, 1]`.The coordinate system of the position depends on the current [view](./deck.md#views): `[longitude, latitude, altitude]` in geospatial views and world position in non-geospatial views.
* `attenuation` = (number[3]) Light attenuation coefficients: `[C_constant, C_linear, C_quadratic]`. Reduces the intensity based on the distance `D` from the light:
```
Intensity = Intensity / (C_constant + C_linear * D + C_quadratic * D * D)
```
* For (approximately) physically correct attenuation, use `attenuation: [1, 0, n]`.
* Default: `[1, 0, 0]` (no attenuation due to distance).

## Source

Expand Down
6 changes: 6 additions & 0 deletions docs/upgrade-guide.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Upgrade Guide

## Upgrading to v9.1

### LightingEffect

- `PointLight.attenuation` was previously ignored. To retain old behavior, use the default (`[1, 0, 0]`).

## Upgrading to v9.0

**Before you upgrade: known issues**
Expand Down
4 changes: 2 additions & 2 deletions modules/aggregation-layers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
"prepublishOnly": "npm run build-bundle && npm run build-bundle -- --env=dev"
},
"dependencies": {
"@luma.gl/constants": "^9.0.17",
"@luma.gl/shadertools": "^9.0.17",
"@luma.gl/constants": "^9.0.23",
"@luma.gl/shadertools": "^9.0.23",
"@math.gl/web-mercator": "^4.0.0",
"d3-hexbin": "^0.2.1"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import {
Layer,
fp64LowPart,
project32,
gouraudLighting,
picking,
LayerProps,
DefaultProps
} from '@deck.gl/core';
import {Layer, fp64LowPart, project32, picking, LayerProps, DefaultProps} from '@deck.gl/core';
import {CubeGeometry} from '@luma.gl/engine';
import {fp64arithmetic} from '@luma.gl/shadertools';
import {fp64arithmetic, gouraudMaterial} from '@luma.gl/shadertools';
import {Model} from '@luma.gl/engine';
import {Buffer} from '@luma.gl/core';
import {GL} from '@luma.gl/constants';
Expand Down Expand Up @@ -89,7 +81,7 @@ export default class GPUGridCellLayer extends Layer<Required<_GPUGridCellLayerPr
return super.getShaders({
vs,
fs,
modules: [project32, gouraudLighting, picking, fp64arithmetic]
modules: [project32, gouraudMaterial, picking, fp64arithmetic]
});
}

Expand Down
2 changes: 1 addition & 1 deletion modules/arcgis/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"prepublishOnly": "npm run build-bundle && npm run build-bundle -- --env=dev"
},
"dependencies": {
"@luma.gl/constants": "^9.0.17",
"@luma.gl/constants": "^9.0.23",
"esri-loader": "^3.7.0"
},
"peerDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions modules/carto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
"@loaders.gl/mvt": "^4.2.0",
"@loaders.gl/schema": "^4.2.0",
"@loaders.gl/tiles": "^4.2.0",
"@luma.gl/core": "^9.0.17",
"@luma.gl/shadertools": "^9.0.17",
"@luma.gl/core": "^9.0.23",
"@luma.gl/shadertools": "^9.0.23",
"@math.gl/web-mercator": "^4.0.0",
"@types/d3-array": "^3.0.2",
"@types/d3-color": "^1.4.2",
Expand Down
10 changes: 5 additions & 5 deletions modules/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@
"dependencies": {
"@loaders.gl/core": "^4.2.0",
"@loaders.gl/images": "^4.2.0",
"@luma.gl/constants": "^9.0.17",
"@luma.gl/core": "^9.0.17",
"@luma.gl/engine": "^9.0.17",
"@luma.gl/shadertools": "^9.0.17",
"@luma.gl/webgl": "^9.0.17",
"@luma.gl/constants": "^9.0.23",
"@luma.gl/core": "^9.0.23",
"@luma.gl/engine": "^9.0.23",
"@luma.gl/shadertools": "^9.0.23",
"@luma.gl/webgl": "^9.0.23",
"@math.gl/core": "^4.0.0",
"@math.gl/sun": "^4.0.0",
"@math.gl/web-mercator": "^4.0.0",
Expand Down
8 changes: 4 additions & 4 deletions modules/core/src/effects/lighting/ambient-light.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const DEFAULT_LIGHT_COLOR = [255, 255, 255];
const DEFAULT_LIGHT_COLOR = [255, 255, 255] as [number, number, number];
const DEFAULT_LIGHT_INTENSITY = 1.0;

let idCount = 0;
Expand All @@ -8,7 +8,7 @@ export type AmbientLightOptions = {
/** Light color, [r, g, b] in the 0-255 range
* @default [255, 255, 255]
*/
color?: number[];
color?: [number, number, number];
/** Light intensity, higher number is brighter
* @default 1.0
*/
Expand All @@ -17,9 +17,9 @@ export type AmbientLightOptions = {

export class AmbientLight {
id: string;
color: number[];
color: [number, number, number];
intensity: number;
type = 'ambient';
type = 'ambient' as const;

constructor(props: AmbientLightOptions = {}) {
const {color = DEFAULT_LIGHT_COLOR} = props;
Expand Down
14 changes: 7 additions & 7 deletions modules/core/src/effects/lighting/directional-light.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {Vector3} from '@math.gl/core';
import type Layer from '../../lib/layer';

const DEFAULT_LIGHT_COLOR = [255, 255, 255];
const DEFAULT_LIGHT_COLOR = [255, 255, 255] as [number, number, number];
const DEFAULT_LIGHT_INTENSITY = 1.0;
const DEFAULT_LIGHT_DIRECTION = [0.0, 0.0, -1.0];
const DEFAULT_LIGHT_DIRECTION = [0.0, 0.0, -1.0] as [number, number, number];

let idCount = 0;

Expand All @@ -12,15 +12,15 @@ export type DirectionalLightOptions = {
/** Light color, [r, g, b] in the 0-255 range
* @default [255, 255, 255]
*/
color?: number[];
color?: [number, number, number];
/** Light intensity, higher number is brighter
* @default 1.0
*/
intensity?: number;
/** Light direction in the common space
* @default [0.0, 0.0, -1.0]
*/
direction?: number[];
direction?: [number, number, number];
/** (Experimental) render shadows cast by this light
* @default false
*/
Expand All @@ -29,10 +29,10 @@ export type DirectionalLightOptions = {

export class DirectionalLight {
id: string;
color: number[];
color: [number, number, number];
intensity: number;
type = 'directional';
direction: number[];
type = 'directional' as const;
direction: [number, number, number];
shadow: boolean;

constructor(props: DirectionalLightOptions = {}) {
Expand Down
34 changes: 17 additions & 17 deletions modules/core/src/effects/lighting/lighting-effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,37 @@ import shadow 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], intensity: 1.0};
const DEFAULT_AMBIENT_LIGHT_PROPS = {
color: [255, 255, 255] as [number, number, number],
intensity: 1.0
};
const DEFAULT_DIRECTIONAL_LIGHT_PROPS = [
{
color: [255, 255, 255],
color: [255, 255, 255] as [number, number, number],
intensity: 1.0,
direction: [-1, 3, -1]
direction: [-1, 3, -1] as [number, number, number]
},
{
color: [255, 255, 255],
color: [255, 255, 255] as [number, number, number],
intensity: 0.9,
direction: [1, -8, -2.5]
direction: [1, -8, -2.5] as [number, number, number]
}
];
const DEFAULT_SHADOW_COLOR = [0, 0, 0, 200 / 255];
const DEFAULT_SHADOW_COLOR = [0, 0, 0, 200 / 255] as [number, number, number, number];

export type LightingEffectProps = Record<string, PointLight | DirectionalLight | AmbientLight>;

// Class to manage ambient, point and directional light sources in deck
export default class LightingEffect implements Effect {
id = 'lighting-effect';
props!: LightingEffectProps;
shadowColor: number[] = DEFAULT_SHADOW_COLOR;
shadowColor: [number, number, number, number] = DEFAULT_SHADOW_COLOR;
context?: EffectContext;

private shadow: boolean = false;
private ambientLight?: AmbientLight | null = null;
private ambientLight?: AmbientLight;
private directionalLights: DirectionalLight[] = [];
private pointLights: PointLight[] = [];
private shadowPasses: ShadowPass[] = [];
Expand Down Expand Up @@ -64,7 +68,7 @@ export default class LightingEffect implements Effect {
}

setProps(props: LightingEffectProps) {
this.ambientLight = null;
this.ambientLight = undefined;
this.directionalLights = [];
this.pointLights = [];

Expand All @@ -77,11 +81,11 @@ export default class LightingEffect implements Effect {
break;

case 'directional':
this.directionalLights.push(lightSource as DirectionalLight);
this.directionalLights.push(lightSource);
break;

case 'point':
this.pointLights.push(lightSource as PointLight);
this.pointLights.push(lightSource);
break;
default:
}
Expand Down Expand Up @@ -121,14 +125,10 @@ export default class LightingEffect implements Effect {

getModuleParameters(layer: Layer) {
const parameters: {
lightSources?: {
ambientLight?: AmbientLight | null;
directionalLights: DirectionalLight[];
pointLights: PointLight[];
};
lightSources?: LightingProps;
shadowMaps?: Texture[];
dummyShadowMap?: Texture | null;
shadowColor?: number[];
shadowColor?: [number, number, number, number];
shadowMatrices?: Matrix4[];
} = this.shadow
? {
Expand Down
27 changes: 12 additions & 15 deletions modules/core/src/effects/lighting/point-light.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import {COORDINATE_SYSTEM} from '../../lib/constants';

import type Layer from '../../lib/layer';

const DEFAULT_LIGHT_COLOR = [255, 255, 255];
const DEFAULT_LIGHT_COLOR = [255, 255, 255] as [number, number, number];
const DEFAULT_LIGHT_INTENSITY = 1.0;
const DEFAULT_ATTENUATION = [0, 0, 1];
const DEFAULT_LIGHT_POSITION = [0.0, 0.0, 1.0];
const DEFAULT_ATTENUATION = [1, 0, 0] as [number, number, number];
const DEFAULT_LIGHT_POSITION = [0.0, 0.0, 1.0] as [number, number, number];

let idCount = 0;

Expand All @@ -15,28 +15,28 @@ export type PointLightOptions = {
/** Light color, [r, g, b] in the 0-255 range
* @default [255, 255, 255]
*/
color?: number[];
color?: [number, number, number];
/** Light intensity, higher number is brighter
* @default 1.0
*/
intensity?: number;
/** Light position [x, y, z] in the common space
* @default [0.0, 0.0, 1.0]
*/
position?: number[];
position?: [number, number, number];
/** Light attenuation
* @default [0.0, 0.0, 1.0]
* @default [1.0, 0.0, 0.0]
*/
attenuation?: number[];
attenuation?: [number, number, number];
};

export class PointLight {
id: string;
color: number[];
color: [number, number, number];
intensity: number;
type = 'point';
position: number[];
attenuation: number[];
type = 'point' as const;
position: [number, number, number];
attenuation: [number, number, number];

protected projectedLight: PointLight;

Expand Down Expand Up @@ -74,12 +74,9 @@ export class PointLight {
}
}

function getAttenuation(props: PointLightOptions): number[] {
function getAttenuation(props: PointLightOptions): [number, number, number] {
if (props.attenuation) {
return props.attenuation;
}
if ('intensity' in props) {
return [0, 0, props.intensity || 0];
}
return DEFAULT_ATTENUATION;
}
8 changes: 6 additions & 2 deletions modules/core/src/effects/lighting/sun-light.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type SunLightOptions = {
/** Light color, [r, g, b] in the 0-255 range
* @default [255, 255, 255]
*/
color?: number[];
color?: [number, number, number];
/** Light intensity, higher number is brighter
* @default 1.0
*/
Expand Down Expand Up @@ -43,7 +43,11 @@ export default class SunLight extends DirectionalLight {
} else {
// @ts-expect-error longitude and latitude are not defined on all viewports
const {latitude, longitude} = viewport;
this.direction = getSunDirection(this.timestamp, latitude, longitude);
this.direction = getSunDirection(this.timestamp, latitude, longitude) as [
number,
number,
number
];
}

return this;
Expand Down
19 changes: 16 additions & 3 deletions modules/core/src/lib/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1076,8 +1076,14 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
if (moduleParameters) {
const {isActive, isAttribute} = moduleParameters.picking;
const {viewport, devicePixelRatio, coordinateSystem, coordinateOrigin} = moduleParameters;
const {modelMatrix} = this.props;
this.setModuleParameters(moduleParameters);
// @ts-expect-error material is not a Layer prop
const {material, modelMatrix} = this.props;

// Do not pass picking module to avoid crash
// TODO remove `setModuleParameters` from codebase
const {picking: _, ...rest} = moduleParameters;
this.setModuleParameters(rest);

const {
// shadow
shadowEnabled,
Expand All @@ -1095,8 +1101,11 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
terrainCover,
drawToTerrainHeightMap,
useTerrainHeightMap,
terrainSkipRender
terrainSkipRender,
// lighting
lightSources
} = moduleParameters;

const shadowProps = {
viewport,
shadowEnabled,
Expand All @@ -1118,11 +1127,15 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
useTerrainHeightMap,
terrainSkipRender
};

this.setShaderModuleProps({
// TODO Revisit whether this is necessary once all layers ported to UBO
shadow: shadowProps,
terrain: terrainProps,
layer: {opacity},
lighting: lightSources,
phongMaterial: material,
gouraudMaterial: material,
picking: {isActive, isAttribute} as PickingProps,
project: {
viewport,
Expand Down
Loading

0 comments on commit e101223

Please sign in to comment.