@luma.gl/shadertools
Version:
Shader module system for luma.gl
93 lines • 3.67 kB
JavaScript
// luma.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import { lightingShader } from "./lights-glsl.js";
const INITIAL_MODULE_OPTIONS = {
lightSources: {}
};
// Take color 0-255 and intensity as input and output 0.0-1.0 range
function convertColor(colorDef = {}) {
const { color = [0, 0, 0], intensity = 1.0 } = colorDef;
return color.map(component => (component * intensity) / 255.0);
}
function getLightSourceUniforms({ ambientLight, pointLights = [], directionalLights = [] }) {
const lightSourceUniforms = {};
if (ambientLight) {
lightSourceUniforms['lighting_uAmbientLight.color'] = convertColor(ambientLight);
}
else {
lightSourceUniforms['lighting_uAmbientLight.color'] = [0, 0, 0];
}
pointLights.forEach((pointLight, index) => {
lightSourceUniforms[`lighting_uPointLight[${index}].color`] = convertColor(pointLight);
lightSourceUniforms[`lighting_uPointLight[${index}].position`] = pointLight.position;
lightSourceUniforms[`lighting_uPointLight[${index}].attenuation`] = pointLight.attenuation || [
1, 0, 0
];
});
lightSourceUniforms.lighting_uPointLightCount = pointLights.length;
directionalLights.forEach((directionalLight, index) => {
lightSourceUniforms[`lighting_uDirectionalLight[${index}].color`] =
convertColor(directionalLight);
lightSourceUniforms[`lighting_uDirectionalLight[${index}].direction`] =
directionalLight.direction;
});
lightSourceUniforms.lighting_uDirectionalLightCount = directionalLights.length;
return lightSourceUniforms;
}
// eslint-disable-next-line complexity
function getUniforms(opts = INITIAL_MODULE_OPTIONS) {
// Specify lights separately
if ('lightSources' in opts) {
const { ambientLight, pointLights, directionalLights } = opts.lightSources || {};
const hasLights = ambientLight ||
(pointLights && pointLights.length > 0) ||
(directionalLights && directionalLights.length > 0);
if (!hasLights) {
return { lighting_uEnabled: false };
}
return Object.assign({}, getLightSourceUniforms({ ambientLight, pointLights, directionalLights }), {
lighting_uEnabled: true
});
}
// Support for array of lights. Type of light is detected by type field
if ('lights' in opts) {
const lightSources = { pointLights: [], directionalLights: [] };
// @ts-expect-error
for (const light of opts.lights || []) {
switch (light.type) {
case 'ambient':
// Note: Only uses last ambient light
// TODO - add ambient light sources on CPU?
lightSources.ambientLight = light;
break;
case 'directional':
lightSources.directionalLights?.push(light);
break;
case 'point':
lightSources.pointLights?.push(light);
break;
default:
// eslint-disable-next-line
// console.warn(light.type);
}
}
// Call the `opts.lightSources`` version
return getUniforms({ lightSources });
}
return {};
}
/**
* An implementation of PBR (Physically-Based Rendering).
* Physically Based Shading of a microfacet surface defined by a glTF material.
*/
export const lights = {
name: 'lights',
vs: lightingShader,
fs: lightingShader,
getUniforms,
defines: {
MAX_LIGHTS: 3
}
};
//# sourceMappingURL=lights.js.map