UNPKG

threepipe

Version:

A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.

158 lines 6.7 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 { AViewerPluginSync } from '../../viewer'; import { uiFolderContainer, uiSlider, uiToggle } from 'uiconfig.js'; import { onChange, serialize } from 'ts-browser-helpers'; import { ProgressivePlugin } from './ProgressivePlugin'; /** * SSAA Plugin * * Jitters the render camera and optionally other cameras in the scene * to create a super-sampled anti-aliasing effect. * This is done across multiple frames by integrating with the ProgressivePlugin * @category Plugins */ let SSAAPlugin = class SSAAPlugin extends AViewerPluginSync { constructor(rendersPerFrame = 1) { super(); this.enabled = true; this.rendersPerFrame = 1; this.jitterRenderCamera = true; this.jitterLightCameras = true; this._hasSetOffsetRC = false; this._hasSetOffsetLC = false; this.trackedJitterCameras = new Set(); // todo register other cameras and light shadows cameras when added to the scene and changed. this.dependencies = [ProgressivePlugin]; this._addSceneObject = (event) => { event.object?.traverse((o) => { if (o && o.shadow && o.shadow.camera && o.shadow.mapSize) { this.trackedJitterCameras.add([o.shadow.camera, o.shadow.mapSize]); } // if (o?.material) { // if (o.material.alphaMap) console.log(o.material) //todo why? // } }); }; this._preRender = () => { const v = this._viewer; if (!v || !this.enabled || v.renderManager.frameCount <= 1) return; this.rendersPerFrame = v.rendersPerFrame; // just to sync. todo: should this be here?. ideally there should be a event fired from the viewer when the prop changes const cam = v.scene.renderCamera; if (this.jitterRenderCamera) this._jitter(cam, { width: v.renderManager.renderSize.x * v.renderManager.renderScale, height: v.renderManager.renderSize.y * v.renderManager.renderScale, }, v.renderManager.frameCount); if (this.jitterLightCameras) this.trackedJitterCameras.forEach((a) => this._jitter(...a, v.renderManager.frameCount)); this._hasSetOffsetRC = this.jitterRenderCamera; this._hasSetOffsetLC = this.jitterLightCameras; v.renderManager.resetShadows(); }; this._postRender = () => { const v = this._viewer; if (!v) return; if (this._hasSetOffsetRC) { this._clearJitter(v.scene.renderCamera); this._hasSetOffsetRC = false; } if (this._hasSetOffsetLC) { this.trackedJitterCameras.forEach(([camera]) => this._clearJitter(camera)); this._hasSetOffsetLC = false; } }; this.jitterOffsets = [ { x: 0, y: 0 }, { x: -0.5, y: 0 }, { x: -0.375, y: -0.25 }, { x: -0.1875, y: -0.125 }, { x: -0.125, y: -0.375 }, { x: 0.0625, y: -0.0625 }, { x: 0.125, y: -0.3125 }, { x: 0.375, y: -0.4375 }, { x: 0.3125, y: -0.1875 }, { x: 0.25, y: 0.0625 }, { x: 0.4375, y: 0.25 }, { x: 0.1875, y: 0.3125 }, { x: 0, y: 0.4375 }, { x: -0.0625, y: 0.1875 }, { x: -0.25, y: 0.375 }, { x: -0.4375, y: 0.5 }, { x: -0.3125, y: 0.125 }, ]; this.rendersPerFrame = rendersPerFrame; } onAdded(viewer) { super.onAdded(viewer); viewer.addEventListener('preRender', this._preRender); viewer.addEventListener('postRender', this._postRender); viewer.scene.addEventListener('addSceneObject', this._addSceneObject); } onRemove(viewer) { viewer.removeEventListener('preRender', this._preRender); viewer.removeEventListener('postRender', this._postRender); viewer.scene.removeEventListener('addSceneObject', this._addSceneObject); return super.onRemove(viewer); } setDirty() { if (!this._viewer) return; this._viewer.rendersPerFrame = this.rendersPerFrame; this._viewer.setDirty(); this.uiConfig?.uiRefresh?.(true, 'postFrame'); } _jitter(camera, size, frameCount) { if (camera.userData.disableJitter) return; if (camera.userData.__jittered) { this._viewer?.console.warn('SSAAPlugin: Camera already jittered'); return; } const sample = { ...this.jitterOffsets[frameCount % this.jitterOffsets.length] }; // const sample = {...offsets[Math.floor(Math.random() * (offsets.length - 0.001))]} // { // sample.x += 1 * (Math.random() - 0.5) // sample.y += 1 * (Math.random() - 0.5) // } camera.setViewOffset(size.width, size.height, sample.x, sample.y, size.width, size.height); camera.userData.__jittered = true; } _clearJitter(camera) { if (!camera.userData.__jittered) return; camera.clearViewOffset(); delete camera.userData.__jittered; } }; SSAAPlugin.PluginType = 'SSAAPlugin'; __decorate([ serialize(), uiToggle('Enabled'), onChange(SSAAPlugin.prototype.setDirty) ], SSAAPlugin.prototype, "enabled", void 0); __decorate([ serialize(), uiSlider('Renders/Frame', [1, 32], 1), onChange(SSAAPlugin.prototype.setDirty) ], SSAAPlugin.prototype, "rendersPerFrame", void 0); __decorate([ serialize(), uiToggle('Render Camera'), onChange(SSAAPlugin.prototype.setDirty) ], SSAAPlugin.prototype, "jitterRenderCamera", void 0); __decorate([ serialize(), uiToggle('Light Cameras'), onChange(SSAAPlugin.prototype.setDirty) ], SSAAPlugin.prototype, "jitterLightCameras", void 0); SSAAPlugin = __decorate([ uiFolderContainer('SSAA Plugin') ], SSAAPlugin); export { SSAAPlugin }; //# sourceMappingURL=SSAAPlugin.js.map