Spaces:
Running
Running
| import { BackSide, FrontSide, CubeUVReflectionMapping } from '../../constants.js'; | |
| import { BoxGeometry } from '../../geometries/BoxGeometry.js'; | |
| import { PlaneGeometry } from '../../geometries/PlaneGeometry.js'; | |
| import { ShaderMaterial } from '../../materials/ShaderMaterial.js'; | |
| import { Color } from '../../math/Color.js'; | |
| import { Mesh } from '../../objects/Mesh.js'; | |
| import { ShaderLib } from '../shaders/ShaderLib.js'; | |
| import { cloneUniforms } from '../shaders/UniformsUtils.js'; | |
| function WebGLBackground(renderer, cubemaps, state, objects, alpha, premultipliedAlpha) { | |
| const clearColor = new Color(0x000000); | |
| let clearAlpha = alpha === true ? 0 : 1; | |
| let planeMesh; | |
| let boxMesh; | |
| let currentBackground = null; | |
| let currentBackgroundVersion = 0; | |
| let currentTonemapping = null; | |
| function render(renderList, scene) { | |
| let forceClear = false; | |
| let background = scene.isScene === true ? scene.background : null; | |
| if (background && background.isTexture) { | |
| background = cubemaps.get(background); | |
| } | |
| // Ignore background in AR | |
| // TODO: Reconsider this. | |
| const xr = renderer.xr; | |
| const session = xr.getSession && xr.getSession(); | |
| if (session && session.environmentBlendMode === 'additive') { | |
| background = null; | |
| } | |
| if (background === null) { | |
| setClear(clearColor, clearAlpha); | |
| } else if (background && background.isColor) { | |
| setClear(background, 1); | |
| forceClear = true; | |
| } | |
| if (renderer.autoClear || forceClear) { | |
| renderer.clear(renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil); | |
| } | |
| if (background && (background.isCubeTexture || background.mapping === CubeUVReflectionMapping)) { | |
| if (boxMesh === undefined) { | |
| boxMesh = new Mesh( | |
| new BoxGeometry(1, 1, 1), | |
| new ShaderMaterial({ | |
| name: 'BackgroundCubeMaterial', | |
| uniforms: cloneUniforms(ShaderLib.cube.uniforms), | |
| vertexShader: ShaderLib.cube.vertexShader, | |
| fragmentShader: ShaderLib.cube.fragmentShader, | |
| side: BackSide, | |
| depthTest: false, | |
| depthWrite: false, | |
| fog: false, | |
| }) | |
| ); | |
| boxMesh.geometry.deleteAttribute('normal'); | |
| boxMesh.geometry.deleteAttribute('uv'); | |
| boxMesh.onBeforeRender = function (renderer, scene, camera) { | |
| this.matrixWorld.copyPosition(camera.matrixWorld); | |
| }; | |
| // enable code injection for non-built-in material | |
| Object.defineProperty(boxMesh.material, 'envMap', { | |
| get: function () { | |
| return this.uniforms.envMap.value; | |
| }, | |
| }); | |
| objects.update(boxMesh); | |
| } | |
| boxMesh.material.uniforms.envMap.value = background; | |
| boxMesh.material.uniforms.flipEnvMap.value = background.isCubeTexture && background.isRenderTargetTexture === false ? -1 : 1; | |
| if (currentBackground !== background || currentBackgroundVersion !== background.version || currentTonemapping !== renderer.toneMapping) { | |
| boxMesh.material.needsUpdate = true; | |
| currentBackground = background; | |
| currentBackgroundVersion = background.version; | |
| currentTonemapping = renderer.toneMapping; | |
| } | |
| // push to the pre-sorted opaque render list | |
| renderList.unshift(boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null); | |
| } else if (background && background.isTexture) { | |
| if (planeMesh === undefined) { | |
| planeMesh = new Mesh( | |
| new PlaneGeometry(2, 2), | |
| new ShaderMaterial({ | |
| name: 'BackgroundMaterial', | |
| uniforms: cloneUniforms(ShaderLib.background.uniforms), | |
| vertexShader: ShaderLib.background.vertexShader, | |
| fragmentShader: ShaderLib.background.fragmentShader, | |
| side: FrontSide, | |
| depthTest: false, | |
| depthWrite: false, | |
| fog: false, | |
| }) | |
| ); | |
| planeMesh.geometry.deleteAttribute('normal'); | |
| // enable code injection for non-built-in material | |
| Object.defineProperty(planeMesh.material, 'map', { | |
| get: function () { | |
| return this.uniforms.t2D.value; | |
| }, | |
| }); | |
| objects.update(planeMesh); | |
| } | |
| planeMesh.material.uniforms.t2D.value = background; | |
| if (background.matrixAutoUpdate === true) { | |
| background.updateMatrix(); | |
| } | |
| planeMesh.material.uniforms.uvTransform.value.copy(background.matrix); | |
| if (currentBackground !== background || currentBackgroundVersion !== background.version || currentTonemapping !== renderer.toneMapping) { | |
| planeMesh.material.needsUpdate = true; | |
| currentBackground = background; | |
| currentBackgroundVersion = background.version; | |
| currentTonemapping = renderer.toneMapping; | |
| } | |
| // push to the pre-sorted opaque render list | |
| renderList.unshift(planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null); | |
| } | |
| } | |
| function setClear(color, alpha) { | |
| state.buffers.color.setClear(color.r, color.g, color.b, alpha, premultipliedAlpha); | |
| } | |
| return { | |
| getClearColor: function () { | |
| return clearColor; | |
| }, | |
| setClearColor: function (color, alpha = 1) { | |
| clearColor.set(color); | |
| clearAlpha = alpha; | |
| setClear(clearColor, clearAlpha); | |
| }, | |
| getClearAlpha: function () { | |
| return clearAlpha; | |
| }, | |
| setClearAlpha: function (alpha) { | |
| clearAlpha = alpha; | |
| setClear(clearColor, clearAlpha); | |
| }, | |
| render: render, | |
| }; | |
| } | |
| export { WebGLBackground }; | |