UNPKG

playcanvas

Version:

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

76 lines (73 loc) 2.57 kB
import { FloatPacking } from '../core/math/float-packing.js'; import { Texture } from '../platform/graphics/texture.js'; import { DeviceCache } from '../platform/graphics/device-cache.js'; import { FILTER_NEAREST, FILTER_LINEAR, TEXTURETYPE_DEFAULT, ADDRESS_CLAMP_TO_EDGE, PIXELFORMAT_RGBA16F } from '../platform/graphics/constants.js'; class AreaLightCacheEntry { destroy() { this.texture0?.destroy(); this.texture1?.destroy(); } constructor(texture0, texture1){ this.texture0 = texture0; this.texture1 = texture1; } } const deviceCache = new DeviceCache(); class AreaLightLuts { static createTexture(device, format, size, postfix = '') { const tex = new Texture(device, { name: `AreaLightLUT${postfix}`, width: size, height: size, format: format, addressU: ADDRESS_CLAMP_TO_EDGE, addressV: ADDRESS_CLAMP_TO_EDGE, type: TEXTURETYPE_DEFAULT, magFilter: FILTER_LINEAR, minFilter: FILTER_NEAREST, anisotropy: 1, mipmaps: false }); return tex; } static applyTextures(device, texture1, texture2) { deviceCache.remove(device); deviceCache.get(device, ()=>{ return new AreaLightCacheEntry(texture1, texture1 === texture2 ? null : texture2); }); device.scope.resolve('areaLightsLutTex1').setValue(texture1); device.scope.resolve('areaLightsLutTex2').setValue(texture2); } static createPlaceholder(device) { const texture = AreaLightLuts.createTexture(device, PIXELFORMAT_RGBA16F, 2, 'placeholder'); const pixels = texture.lock(); pixels.fill(0); texture.unlock(); AreaLightLuts.applyTextures(device, texture, texture); } static set(device, ltcMat1, ltcMat2) { function buildTexture(device, data, format) { const texture = AreaLightLuts.createTexture(device, format, 64); texture.lock().set(data); texture.unlock(); return texture; } function convertToHalfFloat(data) { const count = data.length; const ret = new Uint16Array(count); const float2Half = FloatPacking.float2Half; for(let i = 0; i < count; i++){ ret[i] = float2Half(data[i]); } return ret; } const srcData1 = ltcMat1; const srcData2 = ltcMat2; const data1 = convertToHalfFloat(srcData1); const data2 = convertToHalfFloat(srcData2); const tex1 = buildTexture(device, data1, PIXELFORMAT_RGBA16F); const tex2 = buildTexture(device, data2, PIXELFORMAT_RGBA16F); AreaLightLuts.applyTextures(device, tex1, tex2); } } export { AreaLightLuts };