{"version":3,"file":"ProgressiveLightmap.cjs","sources":["../../src/misc/ProgressiveLightmap.js"],"sourcesContent":["import {\n Scene,\n WebGLRenderTarget,\n FloatType,\n MeshBasicMaterial,\n MeshPhongMaterial,\n DoubleSide,\n PlaneGeometry,\n Mesh,\n} from 'three'\nimport potpack from 'potpack'\nimport { UV1 } from '../_polyfill/uv1'\n\n/**\n * Progressive Light Map Accumulator, by [zalo](https://github.com/zalo/)\n *\n * To use, simply construct a `ProgressiveLightMap` object,\n * `plmap.addObjectsToLightMap(object)` an array of semi-static\n * objects and lights to the class once, and then call\n * `plmap.update(camera)` every frame to begin accumulating\n * lighting samples.\n *\n * This should begin accumulating lightmaps which apply to\n * your objects, so you can start jittering lighting to achieve\n * the texture-space effect you're looking for.\n *\n * @param {WebGLRenderer} renderer A WebGL Rendering Context\n * @param {number} res The side-long dimension of you total lightmap\n */\nclass ProgressiveLightMap {\n constructor(renderer, res = 1024) {\n this.renderer = renderer\n this.res = res\n this.lightMapContainers = []\n this.compiled = false\n this.scene = new Scene()\n this.scene.background = null\n this.tinyTarget = new WebGLRenderTarget(1, 1)\n this.buffer1Active = false\n this.firstUpdate = true\n this.warned = false\n\n // Create the Progressive LightMap Texture\n const format = /(Android|iPad|iPhone|iPod)/g.test(navigator.userAgent) ? alfFloatType : FloatType\n this.progressiveLightMap1 = new WebGLRenderTarget(this.res, this.res, { type: format })\n this.progressiveLightMap2 = new WebGLRenderTarget(this.res, this.res, { type: format })\n\n // Inject some spicy new logic into a standard phong material\n this.uvMat = new MeshPhongMaterial()\n this.uvMat.uniforms = {}\n this.uvMat.onBeforeCompile = (shader) => {\n // Vertex Shader: Set Vertex Positions to the Unwrapped UV Positions\n shader.vertexShader =\n '#define USE_LIGHTMAP\\n' +\n shader.vertexShader.slice(0, -1) +\n `\tgl_Position = vec4((${UV1} - 0.5) * 2.0, 1.0, 1.0); }`\n\n // Fragment Shader: Set Pixels to average in the Previous frame's Shadows\n const bodyStart = shader.fragmentShader.indexOf('void main() {')\n shader.fragmentShader =\n `varying vec2 v${UV1 === 'uv1' ? UV1 : 'Uv2'};\\n` +\n shader.fragmentShader.slice(0, bodyStart) +\n '\tuniform sampler2D previousShadowMap;\\n\tuniform float averagingWindow;\\n' +\n shader.fragmentShader.slice(bodyStart - 1, -1) +\n `\\nvec3 texelOld = texture2D(previousShadowMap, v${UV1 === 'uv1' ? UV1 : 'Uv2'}).rgb;\n\t\t\t\tgl_FragColor.rgb = mix(texelOld, gl_FragColor.rgb, 1.0/averagingWindow);\n\t\t\t}`\n\n // Set the Previous Frame's Texture Buffer and Averaging Window\n shader.uniforms.previousShadowMap = { value: this.progressiveLightMap1.texture }\n shader.uniforms.averagingWindow = { value: 100 }\n\n this.uvMat.uniforms = shader.uniforms\n\n // Set the new Shader to this\n this.uvMat.userData.shader = shader\n\n this.compiled = true\n }\n }\n\n /**\n * Sets these objects' materials' lightmaps and modifies their uv1's.\n * @param {Object3D} objects An array of objects and lights to set up your lightmap.\n */\n addObjectsToLightMap(objects) {\n // Prepare list of UV bounding boxes for packing later...\n this.uv_boxes = []\n const padding = 3 / this.res\n\n for (let ob = 0; ob < objects.length; ob++) {\n const object = objects[ob]\n\n // If this object is a light, simply add it to the internal scene\n if (object.isLight) {\n this.scene.attach(object)\n continue\n }\n\n if (!object.geometry.hasAttribute('uv')) {\n console.warn('All lightmap objects need UVs!')\n continue\n }\n\n if (this.blurringPlane == null) {\n this._initializeBlurPlane(this.res, this.progressiveLightMap1)\n }\n\n // Apply the lightmap to the object\n object.material.lightMap = this.progressiveLightMap2.texture\n object.material.dithering = true\n object.castShadow = true\n object.receiveShadow = true\n object.renderOrder = 1000 + ob\n\n // Prepare UV boxes for potpack\n // TODO: Size these by object surface area\n this.uv_boxes.push({ w: 1 + padding * 2, h: 1 + padding * 2, index: ob })\n\n this.lightMapContainers.push({ basicMat: object.material, object: object })\n\n this.compiled = false\n }\n\n // Pack the objects' lightmap UVs into the same global space\n const dimensions = potpack(this.uv_boxes)\n this.uv_boxes.forEach((box) => {\n const uv1 = objects[box.index].geometry.getAttribute('uv').clone()\n for (let i = 0; i < uv1.array.length; i += uv1.itemSize) {\n uv1.array[i] = (uv1.array[i] + box.x + padding) / dimensions.w\n uv1.array[i + 1] = (uv1.array[i + 1] + box.y + padding) / dimensions.h\n }\n\n objects[box.index].geometry.setAttribute(UV1, uv1)\n objects[box.index].geometry.getAttribute(UV1).needsUpdate = true\n })\n }\n\n /**\n * This function renders each mesh one at a time into their respective surface maps\n * @param {Camera} camera Standard Rendering Camera\n * @param {number} blendWindow When >1, samples will accumulate over time.\n * @param {boolean} blurEdges Whether to fix UV Edges via blurring\n */\n update(camera, blendWindow = 100, blurEdges = true) {\n if (this.blurringPlane == null) {\n return\n }\n\n // Store the original Render Target\n const oldTarget = this.renderer.getRenderTarget()\n\n // The blurring plane applies blur to the seams of the lightmap\n this.blurringPlane.visible = blurEdges\n\n // Steal the Object3D from the real world to our special dimension\n for (let l = 0; l < this.lightMapContainers.length; l++) {\n this.lightMapContainers[l].object.oldScene = this.lightMapContainers[l].object.parent\n this.scene.attach(this.lightMapContainers[l].object)\n }\n\n // Render once normally to initialize everything\n if (this.firstUpdate) {\n this.renderer.setRenderTarget(this.tinyTarget) // Tiny for Speed\n this.renderer.render(this.scene, camera)\n this.firstUpdate = false\n }\n\n // Set each object's material to the UV Unwrapped Surface Mapping Version\n for (let l = 0; l < this.lightMapContainers.length; l++) {\n this.uvMat.uniforms.averagingWindow = { value: blendWindow }\n this.lightMapContainers[l].object.material = this.uvMat\n this.lightMapContainers[l].object.oldFrustumCulled = this.lightMapContainers[l].object.frustumCulled\n this.lightMapContainers[l].object.frustumCulled = false\n }\n\n // Ping-pong two surface buffers for reading/writing\n const activeMap = this.buffer1Active ? this.progressiveLightMap1 : this.progressiveLightMap2\n const inactiveMap = this.buffer1Active ? this.progressiveLightMap2 : this.progressiveLightMap1\n\n // Render the object's surface maps\n this.renderer.setRenderTarget(activeMap)\n this.uvMat.uniforms.previousShadowMap = { value: inactiveMap.texture }\n this.blurringPlane.material.uniforms.previousShadowMap = { value: inactiveMap.texture }\n this.buffer1Active = !this.buffer1Active\n this.renderer.render(this.scene, camera)\n\n // Restore the object's Real-time Material and add it back to the original world\n for (let l = 0; l < this.lightMapContainers.length; l++) {\n this.lightMapContainers[l].object.frustumCulled = this.lightMapContainers[l].object.oldFrustumCulled\n this.lightMapContainers[l].object.material = this.lightMapContainers[l].basicMat\n this.lightMapContainers[l].object.oldScene.attach(this.lightMapContainers[l].object)\n }\n\n // Restore the original Render Target\n this.renderer.setRenderTarget(oldTarget)\n }\n\n /** DEBUG\n * Draw the lightmap in the main scene. Call this after adding the objects to it.\n * @param {boolean} visible Whether the debug plane should be visible\n * @param {Vector3} position Where the debug plane should be drawn\n */\n showDebugLightmap(visible, position = undefined) {\n if (this.lightMapContainers.length == 0) {\n if (!this.warned) {\n console.warn('Call this after adding the objects!')\n this.warned = true\n }\n\n return\n }\n\n if (this.labelMesh == null) {\n this.labelMaterial = new MeshBasicMaterial({\n map: this.progressiveLightMap1.texture,\n side: DoubleSide,\n })\n this.labelPlane = new PlaneGeometry(100, 100)\n this.labelMesh = new Mesh(this.labelPlane, this.labelMaterial)\n this.labelMesh.position.y = 250\n this.lightMapContainers[0].object.parent.add(this.labelMesh)\n }\n\n if (position != undefined) {\n this.labelMesh.position.copy(position)\n }\n\n this.labelMesh.visible = visible\n }\n\n /**\n * INTERNAL Creates the Blurring Plane\n * @param {number} res The square resolution of this object's lightMap.\n * @param {WebGLRenderTexture} lightMap The lightmap to initialize the plane with.\n */\n _initializeBlurPlane(res, lightMap = null) {\n const blurMaterial = new MeshBasicMaterial()\n blurMaterial.uniforms = {\n previousShadowMap: { value: null },\n pixelOffset: { value: 1.0 / res },\n polygonOffset: true,\n polygonOffsetFactor: -1,\n polygonOffsetUnits: 3.0,\n }\n blurMaterial.onBeforeCompile = (shader) => {\n // Vertex Shader: Set Vertex Positions to the Unwrapped UV Positions\n shader.vertexShader =\n '#define USE_UV\\n' + shader.vertexShader.slice(0, -1) + '\tgl_Position = vec4((uv - 0.5) * 2.0, 1.0, 1.0); }'\n\n // Fragment Shader: Set Pixels to 9-tap box blur the current frame's Shadows\n const bodyStart = shader.fragmentShader.indexOf('void main() {')\n shader.fragmentShader =\n '#define USE_UV\\n' +\n shader.fragmentShader.slice(0, bodyStart) +\n '\tuniform sampler2D previousShadowMap;\\n\tuniform float pixelOffset;\\n' +\n shader.fragmentShader.slice(bodyStart - 1, -1) +\n `\tgl_FragColor.rgb = (\n\t\t\t texture2D(previousShadowMap, vUv + vec2( pixelOffset, 0.0 )).rgb +\n\t\t\t texture2D(previousShadowMap, vUv + vec2( 0.0 , pixelOffset)).rgb +\n\t\t\t texture2D(previousShadowMap, vUv + vec2( 0.0 , -pixelOffset)).rgb +\n\t\t\t texture2D(previousShadowMap, vUv + vec2(-pixelOffset, 0.0 )).rgb +\n\t\t\t texture2D(previousShadowMap, vUv + vec2( pixelOffset, pixelOffset)).rgb +\n\t\t\t texture2D(previousShadowMap, vUv + vec2(-pixelOffset, pixelOffset)).rgb +\n\t\t\t texture2D(previousShadowMap, vUv + vec2( pixelOffset, -pixelOffset)).rgb +\n\t\t\t texture2D(previousShadowMap, vUv + vec2(-pixelOffset, -pixelOffset)).rgb)/8.0;\n\t\t}`\n\n // Set the LightMap Accumulation Buffer\n shader.uniforms.previousShadowMap = { value: lightMap.texture }\n shader.uniforms.pixelOffset = { value: 0.5 / res }\n blurMaterial.uniforms = shader.uniforms\n\n // Set the new Shader to this\n blurMaterial.userData.shader = shader\n\n this.compiled = true\n }\n\n this.blurringPlane = new Mesh(new PlaneGeometry(1, 1), blurMaterial)\n this.blurringPlane.name = 'Blurring Plane'\n this.blurringPlane.frustumCulled = false\n this.blurringPlane.renderOrder = 0\n this.blurringPlane.material.depthWrite = false\n this.scene.add(this.blurringPlane)\n }\n}\n\nexport { ProgressiveLightMap }\n"],"names":["Scene","WebGLRenderTarget","FloatType","MeshPhongMaterial","UV1","uv1","MeshBasicMaterial","DoubleSide","PlaneGeometry","Mesh"],"mappings":"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"}