import { AmbientLight, DirectionalLight, DirectionalLightHelper, Light, HemisphereLight, PointLight, SpotLight, RectAreaLight, HemisphereLightHelper, PointLightHelper, OrthographicCamera, PerspectiveCamera, } from 'three' import { reactive } from 'vue' export enum LightType { AmbientLight, DirectionalLight, RectAreaLight, HemisphereLight, PointLight, SpotLight, } export enum LightHelperType { DirectionalLightHelper, RectAreaLightHelper, HemisphereLightHelper, PointLightHelper, SpotLightHelper, } interface LightOptions { color?: string | number groundColor?: string | number intensity?: number width?: number height?: number distance?: number angle?: number penumbra?: number decay?: number shadowBias?: number shadowRadius?: number shadowMapSize?: number shadowCameraNear?: number shadowCameraFar?: number shadowCameraFov?: number shadowCameraVisible?: boolean shadowCameraLeft?: number shadowCameraRight?: number shadowCameraTop?: number shadowCameraBottom?: number castShadow?: boolean helper?: boolean } const state = reactive<{ lights: Array helpers: Array }>({ lights: [], helpers: [], }) export function useLights() { function createLight( type = LightType.AmbientLight, options: LightOptions = { color: 0xffffff, intensity: 1 }, ): { light: Light; helper?: LightHelperType } & Light { let light: Light let helper: any switch (type) { case LightType.AmbientLight: light = new AmbientLight(options.color, options.intensity) break case LightType.DirectionalLight: light = new DirectionalLight(options.color, options.intensity) if (options.helper) { helper = new DirectionalLightHelper(light as DirectionalLight, 5) } light.shadow.mapSize.set(1024, 1024) const lightShadowCamera = light.shadow.camera as PerspectiveCamera | OrthographicCamera if (lightShadowCamera instanceof PerspectiveCamera) { lightShadowCamera.near = options.shadowCameraNear || 0.5 lightShadowCamera.far = options.shadowCameraFar || 500 } if (lightShadowCamera instanceof OrthographicCamera) { lightShadowCamera.left = options.shadowCameraLeft || -100 lightShadowCamera.right = options.shadowCameraRight || 100 lightShadowCamera.top = options.shadowCameraTop || 100 lightShadowCamera.bottom = options.shadowCameraBottom || -100 } break case LightType.RectAreaLight: light = new RectAreaLight(options.color, options.intensity) break case LightType.HemisphereLight: light = new HemisphereLight(options.color, options.groundColor, options.intensity) if (options.helper) { helper = new HemisphereLightHelper(light as HemisphereLight, 15) } break case LightType.PointLight: light = new PointLight(options.color, options.intensity, options.distance, options.decay) if (options.helper) { helper = new PointLightHelper(light as PointLight, 5) } break case LightType.SpotLight: light = new SpotLight( options.color, options.intensity, options.distance, options.angle, options.penumbra, options.decay, ) break default: break } if (options.castShadow) { light.castShadow = options.castShadow } state.lights.push(light) if (options.helper) { state.helpers.push(helper) return { light, helper, } } else { return light } } return { lights: state.lights, createLight, } }