UNPKG

threepipe

Version:

A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.

188 lines 8.8 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { BasicDepthPacking, Color, DoubleSide, FrontSide, MeshDepthMaterial, NoBlending, UnsignedByteType, } from 'three'; import { GBufferRenderPass } from '../../postprocessing'; import { ViewerRenderManager } from '../../viewer'; import { PipelinePassPlugin } from '../base/PipelinePassPlugin'; import { uiDropdown, uiFolderContainer, uiImage } from 'uiconfig.js'; import { shaderReplaceString } from '../../utils'; import { onChange } from 'ts-browser-helpers'; import DepthBufferUnpack from './shaders/DepthBufferPlugin.unpack.glsl'; import { threeConstMappings } from '../../three'; /** * Depth Buffer Plugin * * Adds a pre-render pass to render the depth buffer to a render target that can be used as gbuffer or for postprocessing. * @category Plugins */ let DepthBufferPlugin = class DepthBufferPlugin extends PipelinePassPlugin { _depthPackingChanged() { this.material.depthPacking = this.depthPacking; this.material.needsUpdate = true; if (this.unpackExtension && this.unpackExtension.extraDefines) { this.unpackExtension.extraDefines.DEPTH_PACKING = this.depthPacking; this.unpackExtension.setDirty?.(); } this.setDirty(); } _createTarget(recreate = true) { if (!this._viewer) return; if (recreate) this._disposeTarget(); const rm = this._viewer.renderManager; if (!this.target) this.target = this._viewer.renderManager.createTarget({ depthBuffer: true, samples: this._viewer.renderManager.zPrepass && this.isPrimaryGBuffer && rm.msaa ? // requirement for zPrepass typeof rm.msaa !== 'number' ? ViewerRenderManager.DEFAULT_MSAA_SAMPLES : rm.msaa : 0, type: this.bufferType, // magFilter: NearestFilter, // minFilter: NearestFilter, // generateMipmaps: false, // encoding: LinearEncoding, }); this.texture = this.target.texture; this.texture.name = 'depthBuffer'; // if (this._pass) this._pass.target = this.target if (this.isPrimaryGBuffer) { this._viewer.renderManager.gbufferTarget = this.target; this._viewer.renderManager.gbufferUnpackExtension = this.unpackExtension; this._viewer.renderManager.screenPass.material.registerMaterialExtensions([this.unpackExtension]); this._isPrimaryGBufferSet = true; } } _disposeTarget() { if (!this._viewer) return; if (this.target) { this._viewer.renderManager.disposeTarget(this.target); this.target = undefined; } this.texture = undefined; if (this._isPrimaryGBufferSet) { // using a separate flag as when isPrimaryGBuffer is changed, we cannot check it. this._viewer.renderManager.gbufferTarget = undefined; this._viewer.renderManager.gbufferUnpackExtension = undefined; // this._viewer.renderManager.screenPass.material.unregisterMaterialExtensions([this.unpackExtension]) // todo this has an issue this._isPrimaryGBufferSet = false; } } _createPass() { this._createTarget(true); if (!this.target) throw new Error('DepthBufferPlugin: target not created'); this.material.userData.isGBufferMaterial = true; const pass = new GBufferRenderPass(this.passId, () => this.target, this.material, new Color(0, 0, 0), 1); const preprocessMaterial = pass.preprocessMaterial; pass.preprocessMaterial = (m) => preprocessMaterial(m, m.userData.renderToDepth); // if renderToDepth is undefined then renderToGbuffer is taken internally pass.before = ['render']; pass.after = []; pass.required = ['render']; return pass; } constructor(bufferType = UnsignedByteType, isPrimaryGBuffer = false, enabled = true, depthPacking = BasicDepthPacking) { super(); this.passId = 'depth'; // @uiConfig() // not supported in this material yet this.material = new MeshDepthMaterialOverride({ depthPacking: BasicDepthPacking, blending: NoBlending, transparent: true, }); this.unpackExtension = { shaderExtender: (shader) => { const includes = ['depth_buffer_unpack', 'gbuffer_unpack', 'packing']; const include = includes.find(i => shader.fragmentShader.includes(`#include <${i}>`)); shader.fragmentShader = shaderReplaceString(shader.fragmentShader, `#include <${include}>`, '\n' + DepthBufferUnpack + '\n', { append: include === 'packing' }); }, extraUniforms: { tDepthBuffer: () => ({ value: this.target?.texture }), }, extraDefines: { ['DEPTH_PACKING']: BasicDepthPacking, ['HAS_DEPTH_BUFFER']: () => this.target?.texture ? 1 : undefined, ['HAS_GBUFFER']: () => this.isPrimaryGBuffer && this.target?.texture ? 1 : undefined, }, priority: 100, isCompatible: () => true, }; this._isPrimaryGBufferSet = false; this.enabled = enabled; this.depthPacking = depthPacking; this.bufferType = bufferType; this.isPrimaryGBuffer = isPrimaryGBuffer; } onRemove(viewer) { this._disposeTarget(); return super.onRemove(viewer); } }; DepthBufferPlugin.PluginType = 'DepthBufferPlugin'; __decorate([ uiImage('Depth Buffer', { readOnly: true }) ], DepthBufferPlugin.prototype, "texture", void 0); __decorate([ onChange(DepthBufferPlugin.prototype._depthPackingChanged), uiDropdown('Depth Packing', threeConstMappings.DepthPackingStrategies.uiConfig) ], DepthBufferPlugin.prototype, "depthPacking", void 0); DepthBufferPlugin = __decorate([ uiFolderContainer('Depth Buffer Plugin') ], DepthBufferPlugin); export { DepthBufferPlugin }; class MeshDepthMaterialOverride extends MeshDepthMaterial { constructor(parameters) { super(parameters); this.reset(); } onBeforeRender(renderer, scene, camera, geometry, object) { super.onBeforeRender(renderer, scene, camera, geometry, object); let material = object.material; if (Array.isArray(material)) { // todo: add support for multi materials. material = material[0]; } if (!material) return; if (material.map !== undefined) this.map = material.map; // in case there is alpha in the map. if (material.side !== undefined) this.side = material.side ?? FrontSide; if (material.alphaMap !== undefined) this.alphaMap = material.alphaMap; if (material.alphaTest !== undefined) this.alphaTest = material.alphaTest < 1e-4 ? 1e-4 : material.alphaTest; if (material.alphaHash !== undefined) this.alphaHash = material.alphaHash; if (material.displacementMap !== undefined) this.displacementMap = material.displacementMap; if (material.displacementScale !== undefined) this.displacementScale = material.displacementScale; if (material.displacementBias !== undefined) this.displacementBias = material.displacementBias; if (material.wireframe !== undefined) this.wireframe = material.wireframe; if (material.wireframeLinewidth !== undefined) this.wireframeLinewidth = material.wireframeLinewidth; this.needsUpdate = true; } onAfterRender(renderer, scene, camera, geometry, object) { super.onAfterRender(renderer, scene, camera, geometry, object); this.reset(); } reset() { this.map = null; this.side = DoubleSide; this.alphaMap = null; this.alphaTest = 0.001; this.alphaHash = false; this.displacementMap = null; this.displacementScale = 1; this.displacementBias = 0; this.wireframe = false; this.wireframeLinewidth = 1; } } //# sourceMappingURL=DepthBufferPlugin.js.map