UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

277 lines (262 loc) 13.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebGLShadowMap = WebGLShadowMap; var _constants = require("../../constants.js"); var _WebGLRenderTarget = require("../WebGLRenderTarget.js"); var _MeshDepthMaterial = require("../../materials/MeshDepthMaterial.js"); var _MeshDistanceMaterial = require("../../materials/MeshDistanceMaterial.js"); var _ShaderMaterial = require("../../materials/ShaderMaterial.js"); var _BufferAttribute = require("../../core/BufferAttribute.js"); var _BufferGeometry = require("../../core/BufferGeometry.js"); var _Mesh = require("../../objects/Mesh.js"); var _Vector = require("../../math/Vector4.js"); var _Vector2 = require("../../math/Vector2.js"); var _Frustum = require("../../math/Frustum.js"); var vsm = _interopRequireWildcard(require("../shaders/ShaderLib/vsm.glsl.js")); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function WebGLShadowMap(renderer, objects, capabilities) { let _frustum = new _Frustum.Frustum(); const _shadowMapSize = new _Vector2.Vector2(), _viewportSize = new _Vector2.Vector2(), _viewport = new _Vector.Vector4(), _depthMaterial = new _MeshDepthMaterial.MeshDepthMaterial({ depthPacking: _constants.RGBADepthPacking }), _distanceMaterial = new _MeshDistanceMaterial.MeshDistanceMaterial(), _materialCache = {}, _maxTextureSize = capabilities.maxTextureSize; const shadowSide = { [_constants.FrontSide]: _constants.BackSide, [_constants.BackSide]: _constants.FrontSide, [_constants.DoubleSide]: _constants.DoubleSide }; const shadowMaterialVertical = new _ShaderMaterial.ShaderMaterial({ defines: { VSM_SAMPLES: 8 }, uniforms: { shadow_pass: { value: null }, resolution: { value: new _Vector2.Vector2() }, radius: { value: 4.0 } }, vertexShader: vsm.vertex, fragmentShader: vsm.fragment }); const shadowMaterialHorizontal = shadowMaterialVertical.clone(); shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1; const fullScreenTri = new _BufferGeometry.BufferGeometry(); fullScreenTri.setAttribute('position', new _BufferAttribute.BufferAttribute(new Float32Array([-1, -1, 0.5, 3, -1, 0.5, -1, 3, 0.5]), 3)); const fullScreenMesh = new _Mesh.Mesh(fullScreenTri, shadowMaterialVertical); const scope = this; this.enabled = false; this.autoUpdate = true; this.needsUpdate = false; this.type = _constants.PCFShadowMap; let _previousType = this.type; this.render = function (lights, scene, camera) { if (scope.enabled === false) return; if (scope.autoUpdate === false && scope.needsUpdate === false) return; if (lights.length === 0) return; const currentRenderTarget = renderer.getRenderTarget(); const activeCubeFace = renderer.getActiveCubeFace(); const activeMipmapLevel = renderer.getActiveMipmapLevel(); const _state = renderer.state; // Set GL state for depth map. _state.setBlending(_constants.NoBlending); _state.buffers.color.setClear(1, 1, 1, 1); _state.buffers.depth.setTest(true); _state.setScissorTest(false); // check for shadow map type changes const toVSM = _previousType !== _constants.VSMShadowMap && this.type === _constants.VSMShadowMap; const fromVSM = _previousType === _constants.VSMShadowMap && this.type !== _constants.VSMShadowMap; // render depth map for (let i = 0, il = lights.length; i < il; i++) { const light = lights[i]; const shadow = light.shadow; if (shadow === undefined) { console.warn('THREE.WebGLShadowMap:', light, 'has no shadow.'); continue; } if (shadow.autoUpdate === false && shadow.needsUpdate === false) continue; _shadowMapSize.copy(shadow.mapSize); const shadowFrameExtents = shadow.getFrameExtents(); _shadowMapSize.multiply(shadowFrameExtents); _viewportSize.copy(shadow.mapSize); if (_shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize) { if (_shadowMapSize.x > _maxTextureSize) { _viewportSize.x = Math.floor(_maxTextureSize / shadowFrameExtents.x); _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x; shadow.mapSize.x = _viewportSize.x; } if (_shadowMapSize.y > _maxTextureSize) { _viewportSize.y = Math.floor(_maxTextureSize / shadowFrameExtents.y); _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y; shadow.mapSize.y = _viewportSize.y; } } if (shadow.map === null || toVSM === true || fromVSM === true) { const pars = this.type !== _constants.VSMShadowMap ? { minFilter: _constants.NearestFilter, magFilter: _constants.NearestFilter } : {}; if (shadow.map !== null) { shadow.map.dispose(); } shadow.map = new _WebGLRenderTarget.WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars); shadow.map.texture.name = light.name + '.shadowMap'; shadow.camera.updateProjectionMatrix(); } renderer.setRenderTarget(shadow.map); renderer.clear(); const viewportCount = shadow.getViewportCount(); for (let vp = 0; vp < viewportCount; vp++) { const viewport = shadow.getViewport(vp); _viewport.set(_viewportSize.x * viewport.x, _viewportSize.y * viewport.y, _viewportSize.x * viewport.z, _viewportSize.y * viewport.w); _state.viewport(_viewport); shadow.updateMatrices(light, vp); _frustum = shadow.getFrustum(); renderObject(scene, camera, shadow.camera, light, this.type); } // do blur pass for VSM if (shadow.isPointLightShadow !== true && this.type === _constants.VSMShadowMap) { VSMPass(shadow, camera); } shadow.needsUpdate = false; } _previousType = this.type; scope.needsUpdate = false; renderer.setRenderTarget(currentRenderTarget, activeCubeFace, activeMipmapLevel); }; function VSMPass(shadow, camera) { const geometry = objects.update(fullScreenMesh); if (shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples) { shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples; shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples; shadowMaterialVertical.needsUpdate = true; shadowMaterialHorizontal.needsUpdate = true; } if (shadow.mapPass === null) { shadow.mapPass = new _WebGLRenderTarget.WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y); } // vertical pass shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture; shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize; shadowMaterialVertical.uniforms.radius.value = shadow.radius; renderer.setRenderTarget(shadow.mapPass); renderer.clear(); renderer.renderBufferDirect(camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null); // horizontal pass shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture; shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize; shadowMaterialHorizontal.uniforms.radius.value = shadow.radius; renderer.setRenderTarget(shadow.map); renderer.clear(); renderer.renderBufferDirect(camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null); } function getDepthMaterial(object, material, light, type) { let result = null; const customMaterial = light.isPointLight === true ? object.customDistanceMaterial : object.customDepthMaterial; if (customMaterial !== undefined) { result = customMaterial; } else { result = light.isPointLight === true ? _distanceMaterial : _depthMaterial; if (renderer.localClippingEnabled && material.clipShadows === true && Array.isArray(material.clippingPlanes) && material.clippingPlanes.length !== 0 || material.displacementMap && material.displacementScale !== 0 || material.alphaMap && material.alphaTest > 0 || material.map && material.alphaTest > 0) { // in this case we need a unique material instance reflecting the // appropriate state const keyA = result.uuid, keyB = material.uuid; let materialsForVariant = _materialCache[keyA]; if (materialsForVariant === undefined) { materialsForVariant = {}; _materialCache[keyA] = materialsForVariant; } let cachedMaterial = materialsForVariant[keyB]; if (cachedMaterial === undefined) { cachedMaterial = result.clone(); materialsForVariant[keyB] = cachedMaterial; material.addEventListener('dispose', onMaterialDispose); } result = cachedMaterial; } } result.visible = material.visible; result.wireframe = material.wireframe; if (type === _constants.VSMShadowMap) { result.side = material.shadowSide !== null ? material.shadowSide : material.side; } else { result.side = material.shadowSide !== null ? material.shadowSide : shadowSide[material.side]; } result.alphaMap = material.alphaMap; result.alphaTest = material.alphaTest; result.map = material.map; result.clipShadows = material.clipShadows; result.clippingPlanes = material.clippingPlanes; result.clipIntersection = material.clipIntersection; result.displacementMap = material.displacementMap; result.displacementScale = material.displacementScale; result.displacementBias = material.displacementBias; result.wireframeLinewidth = material.wireframeLinewidth; result.linewidth = material.linewidth; if (light.isPointLight === true && result.isMeshDistanceMaterial === true) { const materialProperties = renderer.properties.get(result); materialProperties.light = light; } return result; } function renderObject(object, camera, shadowCamera, light, type) { if (object.visible === false) return; const visible = object.layers.test(camera.layers); if (visible && (object.isMesh || object.isLine || object.isPoints)) { if ((object.castShadow || object.receiveShadow && type === _constants.VSMShadowMap) && (!object.frustumCulled || _frustum.intersectsObject(object))) { object.modelViewMatrix.multiplyMatrices(shadowCamera.matrixWorldInverse, object.matrixWorld); const geometry = objects.update(object); const material = object.material; if (Array.isArray(material)) { const groups = geometry.groups; for (let k = 0, kl = groups.length; k < kl; k++) { const group = groups[k]; const groupMaterial = material[group.materialIndex]; if (groupMaterial && groupMaterial.visible) { const depthMaterial = getDepthMaterial(object, groupMaterial, light, type); object.onBeforeShadow(renderer, object, camera, shadowCamera, geometry, depthMaterial, group); renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, group); object.onAfterShadow(renderer, object, camera, shadowCamera, geometry, depthMaterial, group); } } } else if (material.visible) { const depthMaterial = getDepthMaterial(object, material, light, type); object.onBeforeShadow(renderer, object, camera, shadowCamera, geometry, depthMaterial, null); renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, null); object.onAfterShadow(renderer, object, camera, shadowCamera, geometry, depthMaterial, null); } } } const children = object.children; for (let i = 0, l = children.length; i < l; i++) { renderObject(children[i], camera, shadowCamera, light, type); } } function onMaterialDispose(event) { const material = event.target; material.removeEventListener('dispose', onMaterialDispose); // make sure to remove the unique distance/depth materials used for shadow map rendering for (const id in _materialCache) { const cache = _materialCache[id]; const uuid = event.target.uuid; if (uuid in cache) { const shadowMaterial = cache[uuid]; shadowMaterial.dispose(); delete cache[uuid]; } } } }