@luma.gl/engine
Version:
3D Engine Components for luma.gl
134 lines (127 loc) • 4.56 kB
JavaScript
// luma.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import { DynamicTexture } from "../dynamic-texture/dynamic-texture.js";
import { ClipSpace } from "./clip-space.js";
const backgroundModule = {
name: 'background',
uniformTypes: {
scale: 'vec2<f32>'
}
};
const BACKGROUND_FS_WGSL = /* wgsl */ `\
var backgroundTexture: texture_2d<f32>;
var backgroundTextureSampler: sampler;
struct backgroundUniforms {
scale: vec2<f32>,
};
var<uniform> background: backgroundUniforms;
fn billboardTexture_getTextureUV(uv: vec2<f32>) -> vec2<f32> {
let scale: vec2<f32> = background.scale;
var position: vec2<f32> = (uv - vec2<f32>(0.5, 0.5)) / scale + vec2<f32>(0.5, 0.5);
return position;
}
fn fragmentMain(inputs: FragmentInputs) -> vec4<f32> {
let position: vec2<f32> = billboardTexture_getTextureUV(inputs.uv);
return textureSample(backgroundTexture, backgroundTextureSampler, position);
}
`;
const BACKGROUND_FS = /* glsl */ `\
#version 300 es
precision highp float;
uniform sampler2D backgroundTexture;
layout(std140) uniform backgroundUniforms {
vec2 scale;
} background;
in vec2 coordinate;
out vec4 fragColor;
vec2 billboardTexture_getTextureUV(vec2 coord) {
vec2 position = (coord - 0.5) / background.scale + 0.5;
return position;
}
void main(void) {
vec2 position = billboardTexture_getTextureUV(coordinate);
fragColor = texture(backgroundTexture, position);
}
`;
/**
* Model that renders a bitmap into the "background", i.e covering the screen
*/
export class BackgroundTextureModel extends ClipSpace {
backgroundTexture = null;
constructor(device, props) {
super(device, {
...props,
id: props.id || 'background-texture-model',
source: BACKGROUND_FS_WGSL,
fs: BACKGROUND_FS,
modules: [...(props.modules || []), backgroundModule],
parameters: {
depthWriteEnabled: false,
...(props.parameters || {}),
...(props.blend
? {
blend: true,
blendColorOperation: 'add',
blendAlphaOperation: 'add',
blendColorSrcFactor: 'one-minus-dst-alpha',
blendColorDstFactor: 'one',
blendAlphaSrcFactor: 'one-minus-dst-alpha',
blendAlphaDstFactor: 'one'
}
: {})
}
});
if (!props.backgroundTexture) {
throw new Error('BackgroundTextureModel requires a backgroundTexture prop');
}
this.setProps(props);
}
/** Update the background texture */
setProps(props) {
const { backgroundTexture } = props;
if (backgroundTexture) {
this.setBindings({ backgroundTexture });
if (backgroundTexture.isReady) {
const texture = backgroundTexture instanceof DynamicTexture
? backgroundTexture.texture
: backgroundTexture;
this.backgroundTexture = texture;
this.updateScale(texture);
}
else {
backgroundTexture.ready.then(texture => {
this.backgroundTexture = texture;
this.updateScale(texture);
});
}
}
}
predraw() {
// this.updateScale(this.backgroundTexture);
super.predraw();
}
updateScale(texture) {
if (!texture) {
// Initial scale to avoid rendering issues before texture is loaded
this.shaderInputs.setProps({ background: { scale: [1, 1] } });
return;
}
const [screenWidth, screenHeight] = this.device.getCanvasContext().getDrawingBufferSize();
const textureWidth = texture.width;
const textureHeight = texture.height;
const screenAspect = screenWidth / screenHeight;
const textureAspect = textureWidth / textureHeight;
let scaleX = 1;
let scaleY = 1;
if (screenAspect > textureAspect) {
scaleY = screenAspect / textureAspect;
}
else {
scaleX = textureAspect / screenAspect;
}
this.shaderInputs.setProps({ background: { scale: [scaleX, scaleY] } });
}
}
//# sourceMappingURL=billboard-texture-model.js.map