UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

68 lines (67 loc) 3.2 kB
import { Color } from "../../../../core/math/color.js"; import { math } from "../../../../core/math/math.js"; import { LIGHTFALLOFF_INVERSESQUARED } from "../../../../scene/constants.js"; import { Light, lightTypes } from "../../../../scene/light.js"; import { Entity } from "../../../entity.js"; const createLight = (gltfLight, node) => { const lightProps = { enabled: false, type: gltfLight.type === "point" ? "omni" : gltfLight.type, color: gltfLight.hasOwnProperty("color") ? new Color(gltfLight.color) : Color.WHITE, // when range is not defined, infinity should be used - but that causes infinity in bounds calculations range: gltfLight.hasOwnProperty("range") ? gltfLight.range : 9999, falloffMode: LIGHTFALLOFF_INVERSESQUARED, // TODO: (engine issue #3252) Set intensity to match glTF specification, which uses physically based values: // - Omni and spot lights use luminous intensity in candela (lm/sr) // - Directional lights use illuminance in lux (lm/m2). // Current implementation: clamps specified intensity to 0..2 range intensity: gltfLight.hasOwnProperty("intensity") ? math.clamp(gltfLight.intensity, 0, 2) : 1 }; if (gltfLight.hasOwnProperty("spot")) { lightProps.innerConeAngle = gltfLight.spot.hasOwnProperty("innerConeAngle") ? gltfLight.spot.innerConeAngle * math.RAD_TO_DEG : 0; lightProps.outerConeAngle = gltfLight.spot.hasOwnProperty("outerConeAngle") ? gltfLight.spot.outerConeAngle * math.RAD_TO_DEG : 45; } if (gltfLight.hasOwnProperty("intensity")) { const outerAngleRad = gltfLight.spot?.outerConeAngle ?? Math.PI / 4; const innerAngleRad = gltfLight.spot?.innerConeAngle ?? 0; lightProps.luminance = gltfLight.intensity * Light.getLightUnitConversion(lightTypes[lightProps.type], outerAngleRad, innerAngleRad); } const lightEntity = new Entity(node.name); lightEntity.rotateLocal(90, 0, 0); lightEntity.addComponent("light", lightProps); return lightEntity; }; const createLights = (gltf, nodes, options) => { let lights = null; if (gltf.hasOwnProperty("nodes") && gltf.hasOwnProperty("extensions") && gltf.extensions.hasOwnProperty("KHR_lights_punctual") && gltf.extensions.KHR_lights_punctual.hasOwnProperty("lights")) { const gltfLights = gltf.extensions.KHR_lights_punctual.lights; if (gltfLights.length) { const preprocess = options?.light?.preprocess; const process = options?.light?.process ?? createLight; const postprocess = options?.light?.postprocess; gltf.nodes.forEach((gltfNode, nodeIndex) => { if (gltfNode.hasOwnProperty("extensions") && gltfNode.extensions.hasOwnProperty("KHR_lights_punctual") && gltfNode.extensions.KHR_lights_punctual.hasOwnProperty("light")) { const lightIndex = gltfNode.extensions.KHR_lights_punctual.light; const gltfLight = gltfLights[lightIndex]; if (gltfLight) { if (preprocess) { preprocess(gltfLight); } const light = process(gltfLight, nodes[nodeIndex]); if (postprocess) { postprocess(gltfLight, light); } if (light) { if (!lights) lights = /* @__PURE__ */ new Map(); lights.set(gltfNode, light); } } } }); } } return lights; }; export { createLights };