import * as THREE from 'three' ; import { renderAtlas , AtlasMap } from './atlas' ; import { LightProbeSettings , DEFAULT_LIGHT_PROBE_SETTINGS } from './lightProbe' ; import { computeAutoUV2Layout } from './AutoUV2' ; export interface Workbench { aoMode : boolean ; aoDistance : number ; emissiveMultiplier : number ; bounceMultiplier : number ; lightScene : THREE . Scene ; atlasMap : AtlasMap ; irradiance : THREE . Texture ; irradianceData : Float32Array ; settings : LightProbeSettings ; } const DEFAULT_LIGHTMAP_SIZE = 64 ; const DEFAULT_TEXELS_PER_UNIT = 2 ; const DEFAULT_AO_DISTANCE = 3 ; const DEFAULT_EMISSIVE_MULTIPLIER = 32 ; function createRendererTexture ( atlasWidth , atlasHeight , textureFilter ) { const atlasSize = atlasWidth * atlasHeight ; const data = new Float32Array ( 4 * atlasSize ) ; const texture = new THREE . DataTexture ( data , atlasWidth , atlasHeight , THREE . RGBAFormat , THREE . FloatType ) ; texture . magFilter = textureFilter ; texture . minFilter = textureFilter ; texture . generateMipmaps = false ; return [ texture , data ] ; } function requestNextTick ( ) { return new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) ) ; } export type SamplerSettings = Partial < LightProbeSettings > ; export interface WorkbenchSettings { ao ? : boolean ; aoDistance ? : number ; emissiveMultiplier ? : number ; bounceMultiplier ? : number ; lightMapSize ? : number | [ number , number ] ; textureFilter ? : THREE . TextureFilter ; texelsPerUnit ? : number ; samplerSettings ? : SamplerSettings ; } export async function initializeWorkbench ( scene , props , requestWork ) { const { ao , aoDistance , emissiveMultiplier , bounceMultiplier , lightMapSize , textureFilter , texelsPerUnit , samplerSettings } = props ; const settings = { ... DEFAULT_LIGHT_PROBE_SETTINGS , ... samplerSettings } ; const [ initialWidth , initialHeight ] = lightMapSize ? [ typeof lightMapSize === 'number' ? lightMapSize : lightMapSize [ 0 ] , typeof lightMapSize === 'number' ? lightMapSize : lightMapSize [ 1 ] ] : [ undefined , undefined ] ; await requestNextTick ( ) ; const [ computedWidth , computedHeight ] = computeAutoUV2Layout ( initialWidth , initialHeight , scene , { texelsPerUnit : texelsPerUnit || DEFAULT_TEXELS_PER_UNIT } ) ; const lightMapWidth = computedWidth || DEFAULT_LIGHTMAP_SIZE ; const lightMapHeight = computedHeight || DEFAULT_LIGHTMAP_SIZE ; await requestNextTick ( ) ; const [ irradiance , irradianceData ] = createRendererTexture ( lightMapWidth , lightMapHeight , textureFilter || THREE . LinearFilter ) ; const gl = await requestWork ( ) ; const atlasMap = renderAtlas ( gl , lightMapWidth , lightMapHeight , scene ) ; return { aoMode : ! ! ao , aoDistance : aoDistance || DEFAULT_AO_DISTANCE , emissiveMultiplier : emissiveMultiplier === undefined ? DEFAULT_EMISSIVE_MULTIPLIER : emissiveMultiplier , bounceMultiplier : bounceMultiplier === undefined ? 1 : bounceMultiplier , lightScene : scene , atlasMap , irradiance , irradianceData , settings : settings } ; }