diff --git a/modules/layers/src/bitmap-layer/bitmap-layer-fragment.ts b/modules/layers/src/bitmap-layer/bitmap-layer-fragment.ts index 8220e69ed72..eac066b5c07 100644 --- a/modules/layers/src/bitmap-layer/bitmap-layer-fragment.ts +++ b/modules/layers/src/bitmap-layer/bitmap-layer-fragment.ts @@ -40,6 +40,8 @@ uniform sampler2D bitmapTexture; in vec2 vTexCoord; in vec2 vTexPos; +in vec3 cameraPosition; +in vec4 position_commonspace; out vec4 fragColor; @@ -110,11 +112,22 @@ void main(void) { } vec4 bitmapColor = texture(bitmapTexture, uv); - fragColor = apply_opacity(color_tint(color_desaturate(bitmapColor.rgb)), bitmapColor.a * layer.opacity); + vec3 bitmapColorRgb = color_tint(color_desaturate(bitmapColor.rgb)); + fragColor = apply_opacity(bitmapColorRgb, bitmapColor.a * layer.opacity); geometry.uv = uv; DECKGL_FILTER_COLOR(fragColor, geometry); + if (!bool(picking.isActive)) { + vec3 normal = normalize(cross(dFdx(position_commonspace.xyz), dFdy(position_commonspace.xyz))); + fragColor.rgb = lighting_getLightColor( + fragColor.rgb, + cameraPosition, + position_commonspace.xyz, + normal + ); + } + if (bool(picking.isActive) && !bool(picking.isAttribute)) { // Since instance information is not used, we can use picking color for pixel index fragColor.rgb = packUVsIntoRGB(uv); diff --git a/modules/layers/src/bitmap-layer/bitmap-layer-vertex.ts b/modules/layers/src/bitmap-layer/bitmap-layer-vertex.ts index 4d489f89297..ae20e9f1318 100644 --- a/modules/layers/src/bitmap-layer/bitmap-layer-vertex.ts +++ b/modules/layers/src/bitmap-layer/bitmap-layer-vertex.ts @@ -12,6 +12,8 @@ in vec3 positions64Low; out vec2 vTexCoord; out vec2 vTexPos; +out vec3 cameraPosition; +out vec4 position_commonspace; const vec3 pickingColor = vec3(1.0, 0.0, 0.0); @@ -21,6 +23,8 @@ void main(void) { geometry.pickingColor = pickingColor; gl_Position = project_position_to_clipspace(positions, positions64Low, vec3(0.0), geometry.position); + position_commonspace = geometry.position; + cameraPosition = project.cameraPosition; DECKGL_FILTER_GL_POSITION(gl_Position, geometry); vTexCoord = texCoords; diff --git a/modules/layers/src/bitmap-layer/bitmap-layer.ts b/modules/layers/src/bitmap-layer/bitmap-layer.ts index 3f5c7be75a6..21c552e62b6 100644 --- a/modules/layers/src/bitmap-layer/bitmap-layer.ts +++ b/modules/layers/src/bitmap-layer/bitmap-layer.ts @@ -14,7 +14,9 @@ import { Color, TextureSource, Position, - DefaultProps + DefaultProps, + Material, + phongMaterial } from '@deck.gl/core'; import {Model} from '@luma.gl/engine'; import type {SamplerProps, Texture} from '@luma.gl/core'; @@ -38,6 +40,8 @@ const defaultProps: DefaultProps = { transparentColor: {type: 'color', value: [0, 0, 0, 0]}, tintColor: {type: 'color', value: [255, 255, 255]}, + material: false, + textureParameters: {type: 'object', ignore: true, value: null} }; @@ -92,6 +96,14 @@ type _BitmapLayerProps = { */ tintColor?: Color; + /** + * Material settings for lighting effect. + * + * @default false + * @see https://deck.gl/docs/developer-guide/using-lighting + */ + material?: Material; + /** Customize the [texture parameters](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texParameter). */ textureParameters?: SamplerProps | null; }; @@ -129,7 +141,7 @@ export default class BitmapLayer extends Layer< }; getShaders() { - return super.getShaders({vs, fs, modules: [project32, picking, bitmapUniforms]}); + return super.getShaders({vs, fs, modules: [project32, phongMaterial, picking, bitmapUniforms]}); } initializeState() { diff --git a/test/modules/layers/bitmap-layer.spec.ts b/test/modules/layers/bitmap-layer.spec.ts index bfc4bccc619..179c623fa03 100644 --- a/test/modules/layers/bitmap-layer.spec.ts +++ b/test/modules/layers/bitmap-layer.spec.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors -import {test, expect} from 'vitest'; +import {test, expect, vi} from 'vitest'; import {COORDINATE_SYSTEM, _GlobeViewport as GlobeViewport} from '@deck.gl/core'; import {BitmapLayer} from '@deck.gl/layers'; @@ -21,7 +21,14 @@ test('BitmapLayer#constructor', () => { testCases: [ { title: 'Empty layer', - props: {id: 'empty'} + props: {id: 'empty'}, + onAfterUpdate({layer}) { + const modules = layer + .getModels()[0] + .shaderInputs.getModules() + .map(module => module.name); + expect(modules, 'uses lighting material shader module').toContain('phongMaterial'); + } }, { title: 'Null layer', @@ -180,6 +187,53 @@ test('createMesh', () => { expect(result3.positions.length, 'returns 9 vertices').toBe(3 * 9); }); +test('BitmapLayer#draw', () => { + testLayer({ + Layer: BitmapLayer, + onError: err => expect(err).toBeFalsy(), + testCases: [ + { + title: 'sets bitmap uniforms and draws', + props: { + id: 'image', + image: { + width: 8, + height: 8, + data: new Uint8Array(8 * 8 * 4).fill(200) + }, + bounds: [0, 0, 1, 1], + desaturate: 0.5, + tintColor: [128, 64, 255], + transparentColor: [1, 2, 3, 4] + }, + onAfterUpdate({layer}) { + const model = layer.state.model!; + const setProps = vi.spyOn(model.shaderInputs, 'setProps'); + const draw = vi.spyOn(model, 'draw').mockImplementation(() => {}); + + layer.draw({shaderModuleProps: {picking: {isActive: false}}} as any); + + expect(setProps).toHaveBeenCalledWith({ + bitmap: { + bitmapTexture: layer.props.image, + bounds: [0, 0, 0, 0], + coordinateConversion: 0, + desaturate: 0.5, + tintColor: [128 / 255, 64 / 255, 1], + transparentColor: [1 / 255, 2 / 255, 3 / 255, 4 / 255] + } + }); + expect(draw).toHaveBeenCalledWith(layer.context.renderPass); + + layer.disablePickingIndex(); + layer.draw({shaderModuleProps: {picking: {isActive: true}}} as any); + expect(draw).toHaveBeenCalledTimes(1); + } + } + ] + }); +}); + test('BitmapLayer#picking', async () => { await testPickingLayer({ layer: new BitmapLayer({ diff --git a/test/render/golden-images/bitmap-imagecoordinates.png b/test/render/golden-images/bitmap-imagecoordinates.png index 00cbb50ae19..73f78dbc0fe 100644 Binary files a/test/render/golden-images/bitmap-imagecoordinates.png and b/test/render/golden-images/bitmap-imagecoordinates.png differ diff --git a/test/render/golden-images/bitmap.png b/test/render/golden-images/bitmap.png index 5539fb6cfde..3393f20d265 100644 Binary files a/test/render/golden-images/bitmap.png and b/test/render/golden-images/bitmap.png differ