{"version":3,"file":"XREstimatedLight.cjs","sources":["../../src/webxr/XREstimatedLight.js"],"sourcesContent":["import { DirectionalLight, Group, LightProbe, WebGLCubeRenderTarget } from 'three'\n\nclass SessionLightProbe {\n constructor(xrLight, renderer, lightProbe, environmentEstimation, estimationStartCallback) {\n this.xrLight = xrLight\n this.renderer = renderer\n this.lightProbe = lightProbe\n this.xrWebGLBinding = null\n this.estimationStartCallback = estimationStartCallback\n this.frameCallback = this.onXRFrame.bind(this)\n\n const session = renderer.xr.getSession()\n\n // If the XRWebGLBinding class is available then we can also query an\n // estimated reflection cube map.\n if (environmentEstimation && 'XRWebGLBinding' in window) {\n // This is the simplest way I know of to initialize a WebGL cubemap in Three.\n const cubeRenderTarget = new WebGLCubeRenderTarget(16)\n xrLight.environment = cubeRenderTarget.texture\n\n const gl = renderer.getContext()\n\n // Ensure that we have any extensions needed to use the preferred cube map format.\n switch (session.preferredReflectionFormat) {\n case 'srgba8':\n gl.getExtension('EXT_sRGB')\n break\n\n case 'rgba16f':\n gl.getExtension('OES_texture_half_float')\n break\n }\n\n this.xrWebGLBinding = new XRWebGLBinding(session, gl)\n\n this.lightProbe.addEventListener('reflectionchange', () => {\n this.updateReflection()\n })\n }\n\n // Start monitoring the XR animation frame loop to look for lighting\n // estimation changes.\n session.requestAnimationFrame(this.frameCallback)\n }\n\n updateReflection() {\n const textureProperties = this.renderer.properties.get(this.xrLight.environment)\n\n if (textureProperties) {\n const cubeMap = this.xrWebGLBinding.getReflectionCubeMap(this.lightProbe)\n\n if (cubeMap) {\n textureProperties.__webglTexture = cubeMap\n\n this.xrLight.environment.needsPMREMUpdate = true\n }\n }\n }\n\n onXRFrame(time, xrFrame) {\n // If either this obejct or the XREstimatedLight has been destroyed, stop\n // running the frame loop.\n if (!this.xrLight) {\n return\n }\n\n const session = xrFrame.session\n session.requestAnimationFrame(this.frameCallback)\n\n const lightEstimate = xrFrame.getLightEstimate(this.lightProbe)\n if (lightEstimate) {\n // We can copy the estimate's spherical harmonics array directly into the light probe.\n this.xrLight.lightProbe.sh.fromArray(lightEstimate.sphericalHarmonicsCoefficients)\n this.xrLight.lightProbe.intensity = 1.0\n\n // For the directional light we have to normalize the color and set the scalar as the\n // intensity, since WebXR can return color values that exceed 1.0.\n const intensityScalar = Math.max(\n 1.0,\n Math.max(\n lightEstimate.primaryLightIntensity.x,\n Math.max(lightEstimate.primaryLightIntensity.y, lightEstimate.primaryLightIntensity.z),\n ),\n )\n\n this.xrLight.directionalLight.color.setRGB(\n lightEstimate.primaryLightIntensity.x / intensityScalar,\n lightEstimate.primaryLightIntensity.y / intensityScalar,\n lightEstimate.primaryLightIntensity.z / intensityScalar,\n )\n this.xrLight.directionalLight.intensity = intensityScalar\n this.xrLight.directionalLight.position.copy(lightEstimate.primaryLightDirection)\n\n if (this.estimationStartCallback) {\n this.estimationStartCallback()\n this.estimationStartCallback = null\n }\n }\n }\n\n dispose() {\n this.xrLight = null\n this.renderer = null\n this.lightProbe = null\n this.xrWebGLBinding = null\n }\n}\n\nexport class XREstimatedLight extends Group {\n constructor(renderer, environmentEstimation = true) {\n super()\n\n this.lightProbe = new LightProbe()\n this.lightProbe.intensity = 0\n this.add(this.lightProbe)\n\n this.directionalLight = new DirectionalLight()\n this.directionalLight.intensity = 0\n this.add(this.directionalLight)\n\n // Will be set to a cube map in the SessionLightProbe is environment estimation is\n // available and requested.\n this.environment = null\n\n let sessionLightProbe = null\n let estimationStarted = false\n renderer.xr.addEventListener('sessionstart', () => {\n const session = renderer.xr.getSession()\n\n if ('requestLightProbe' in session) {\n session\n .requestLightProbe({\n reflectionFormat: session.preferredReflectionFormat,\n })\n .then((probe) => {\n sessionLightProbe = new SessionLightProbe(this, renderer, probe, environmentEstimation, () => {\n estimationStarted = true\n\n // Fired to indicate that the estimated lighting values are now being updated.\n this.dispatchEvent({ type: 'estimationstart' })\n })\n })\n }\n })\n\n renderer.xr.addEventListener('sessionend', () => {\n if (sessionLightProbe) {\n sessionLightProbe.dispose()\n sessionLightProbe = null\n }\n\n if (estimationStarted) {\n // Fired to indicate that the estimated lighting values are no longer being updated.\n this.dispatchEvent({ type: 'estimationend' })\n }\n })\n\n // Done inline to provide access to sessionLightProbe.\n this.dispose = () => {\n if (sessionLightProbe) {\n sessionLightProbe.dispose()\n sessionLightProbe = null\n }\n\n this.remove(this.lightProbe)\n this.lightProbe = null\n\n this.remove(this.directionalLight)\n this.directionalLight = null\n\n this.environment = null\n }\n }\n}\n"],"names":["WebGLCubeRenderTarget","Group","LightProbe","DirectionalLight"],"mappings":";;;AAEA,MAAM,kBAAkB;AAAA,EACtB,YAAY,SAAS,UAAU,YAAY,uBAAuB,yBAAyB;AACzF,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,iBAAiB;AACtB,SAAK,0BAA0B;AAC/B,SAAK,gBAAgB,KAAK,UAAU,KAAK,IAAI;AAE7C,UAAM,UAAU,SAAS,GAAG,WAAY;AAIxC,QAAI,yBAAyB,oBAAoB,QAAQ;AAEvD,YAAM,mBAAmB,IAAIA,MAAqB,sBAAC,EAAE;AACrD,cAAQ,cAAc,iBAAiB;AAEvC,YAAM,KAAK,SAAS,WAAY;AAGhC,cAAQ,QAAQ,2BAAyB;AAAA,QACvC,KAAK;AACH,aAAG,aAAa,UAAU;AAC1B;AAAA,QAEF,KAAK;AACH,aAAG,aAAa,wBAAwB;AACxC;AAAA,MACH;AAED,WAAK,iBAAiB,IAAI,eAAe,SAAS,EAAE;AAEpD,WAAK,WAAW,iBAAiB,oBAAoB,MAAM;AACzD,aAAK,iBAAkB;AAAA,MAC/B,CAAO;AAAA,IACF;AAID,YAAQ,sBAAsB,KAAK,aAAa;AAAA,EACjD;AAAA,EAED,mBAAmB;AACjB,UAAM,oBAAoB,KAAK,SAAS,WAAW,IAAI,KAAK,QAAQ,WAAW;AAE/E,QAAI,mBAAmB;AACrB,YAAM,UAAU,KAAK,eAAe,qBAAqB,KAAK,UAAU;AAExE,UAAI,SAAS;AACX,0BAAkB,iBAAiB;AAEnC,aAAK,QAAQ,YAAY,mBAAmB;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAAA,EAED,UAAU,MAAM,SAAS;AAGvB,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACD;AAED,UAAM,UAAU,QAAQ;AACxB,YAAQ,sBAAsB,KAAK,aAAa;AAEhD,UAAM,gBAAgB,QAAQ,iBAAiB,KAAK,UAAU;AAC9D,QAAI,eAAe;AAEjB,WAAK,QAAQ,WAAW,GAAG,UAAU,cAAc,8BAA8B;AACjF,WAAK,QAAQ,WAAW,YAAY;AAIpC,YAAM,kBAAkB,KAAK;AAAA,QAC3B;AAAA,QACA,KAAK;AAAA,UACH,cAAc,sBAAsB;AAAA,UACpC,KAAK,IAAI,cAAc,sBAAsB,GAAG,cAAc,sBAAsB,CAAC;AAAA,QACtF;AAAA,MACF;AAED,WAAK,QAAQ,iBAAiB,MAAM;AAAA,QAClC,cAAc,sBAAsB,IAAI;AAAA,QACxC,cAAc,sBAAsB,IAAI;AAAA,QACxC,cAAc,sBAAsB,IAAI;AAAA,MACzC;AACD,WAAK,QAAQ,iBAAiB,YAAY;AAC1C,WAAK,QAAQ,iBAAiB,SAAS,KAAK,cAAc,qBAAqB;AAE/E,UAAI,KAAK,yBAAyB;AAChC,aAAK,wBAAyB;AAC9B,aAAK,0BAA0B;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAED,UAAU;AACR,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,iBAAiB;AAAA,EACvB;AACH;AAEO,MAAM,yBAAyBC,MAAAA,MAAM;AAAA,EAC1C,YAAY,UAAU,wBAAwB,MAAM;AAClD,UAAO;AAEP,SAAK,aAAa,IAAIC,iBAAY;AAClC,SAAK,WAAW,YAAY;AAC5B,SAAK,IAAI,KAAK,UAAU;AAExB,SAAK,mBAAmB,IAAIC,uBAAkB;AAC9C,SAAK,iBAAiB,YAAY;AAClC,SAAK,IAAI,KAAK,gBAAgB;AAI9B,SAAK,cAAc;AAEnB,QAAI,oBAAoB;AACxB,QAAI,oBAAoB;AACxB,aAAS,GAAG,iBAAiB,gBAAgB,MAAM;AACjD,YAAM,UAAU,SAAS,GAAG,WAAY;AAExC,UAAI,uBAAuB,SAAS;AAClC,gBACG,kBAAkB;AAAA,UACjB,kBAAkB,QAAQ;AAAA,QACtC,CAAW,EACA,KAAK,CAAC,UAAU;AACf,8BAAoB,IAAI,kBAAkB,MAAM,UAAU,OAAO,uBAAuB,MAAM;AAC5F,gCAAoB;AAGpB,iBAAK,cAAc,EAAE,MAAM,kBAAiB,CAAE;AAAA,UAC5D,CAAa;AAAA,QACb,CAAW;AAAA,MACJ;AAAA,IACP,CAAK;AAED,aAAS,GAAG,iBAAiB,cAAc,MAAM;AAC/C,UAAI,mBAAmB;AACrB,0BAAkB,QAAS;AAC3B,4BAAoB;AAAA,MACrB;AAED,UAAI,mBAAmB;AAErB,aAAK,cAAc,EAAE,MAAM,gBAAe,CAAE;AAAA,MAC7C;AAAA,IACP,CAAK;AAGD,SAAK,UAAU,MAAM;AACnB,UAAI,mBAAmB;AACrB,0BAAkB,QAAS;AAC3B,4BAAoB;AAAA,MACrB;AAED,WAAK,OAAO,KAAK,UAAU;AAC3B,WAAK,aAAa;AAElB,WAAK,OAAO,KAAK,gBAAgB;AACjC,WAAK,mBAAmB;AAExB,WAAK,cAAc;AAAA,IACpB;AAAA,EACF;AACH;;"}