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.
99 lines (88 loc) • 4.22 kB
text/typescript
import {IRenderTarget, RenderManager} from '../rendering'
import {HalfFloatType, LinearFilter, NoColorSpace, RGBM16ColorSpace, UnsignedByteType} from 'three'
import {IRenderManagerOptions, IScene} from '../core'
import {ExtendedRenderPass, ScreenPass, TViewerScreenShader} from '../postprocessing'
import {uiFolderContainer, UiObjectConfig} from 'uiconfig.js'
import {MaterialExtension} from '../materials'
import {onChange3} from 'ts-browser-helpers'
import {IRenderManagerEventMap} from '../core/IRenderer'
export interface ViewerRenderManagerOptions extends IRenderManagerOptions {
rgbm?: boolean,
msaa?: boolean | number,
depthBuffer?: boolean,
stencilBuffer?: boolean,
zPrepass?: boolean,
screenShader?: TViewerScreenShader
maxHDRIntensity?: number
}
export interface ViewerRenderManagerEventMap extends IRenderManagerEventMap{
gbufferUnpackExtensionChanged: {
key: string;
value: any;
oldValue: any;
// target: TTarget;
}
}
('Render Manager')
export class ViewerRenderManager extends RenderManager<ViewerRenderManagerEventMap> {
readonly rgbm: boolean
readonly msaa: boolean | number
readonly depthBuffer: boolean
readonly zPrepass: boolean
readonly maxHDRIntensity: number
readonly renderPass: ExtendedRenderPass
readonly screenPass: ScreenPass
declare uiConfig: UiObjectConfig
static DEFAULT_MSAA_SAMPLES = 4
constructor({rgbm = true, msaa = false, depthBuffer = true, stencilBuffer = false, ...options}: ViewerRenderManagerOptions) {
super({
...options,
targetOptions: {
samples: 0,
// samples: msaa ? typeof msaa !== 'number' ? ViewerRenderManager.DEFAULT_MSAA_SAMPLES : msaa : 0,
colorSpace: rgbm ? RGBM16ColorSpace : NoColorSpace,
type: rgbm ? UnsignedByteType : HalfFloatType,
depthBuffer: depthBuffer,
stencilBuffer: stencilBuffer,
generateMipmaps: /* msaa ? true : */false, // todo: hack for now, fix blurTransmissionTarget in ExtendedRenderPass
minFilter: /* msaa ? LinearMipMapLinearFilter : */LinearFilter, // todo: hack for now, fix blurTransmissionTarget in ExtendedRenderPass
},
})
this.rgbm = rgbm
this.msaa = msaa && this.isWebGL2
this.depthBuffer = depthBuffer
this.zPrepass = options.zPrepass || false
this.maxHDRIntensity = options.maxHDRIntensity ?? (rgbm ? 16 : 72)
let doTransmissionFix = true // const for debugging, todo could be made into a static prop maybe?
if (!this._renderer.userData) {
doTransmissionFix = false
this._renderer.userData = {__isIWebGLRenderer: true}
}
this._renderer.userData.renderTransmissionPass = !doTransmissionFix // hack. used in WebGLRenderer.js
this.renderPass = new ExtendedRenderPass(this)
this.screenPass = new ScreenPass(options.screenShader || '')
this.registerPass(this.renderPass)
this.registerPass(this.screenPass)
}
/**
* Reference to the gbuffer target, if it exists. This can be set by plugins like {@link DepthBufferPlugin}, {@link GBufferPlugin}
*/
gbufferTarget: IRenderTarget | undefined
/**
* The extension that can be used to upload and unpack the values in gbuffer target(s), if it exists. This can be set by plugins like {@link DepthBufferPlugin}, {@link GBufferPlugin}
* Note: this should not be changed after set by some plugin.
*/
(ViewerRenderManager.prototype._gbufferUnpackExtensionChanged)
gbufferUnpackExtension: MaterialExtension | undefined
private _gbufferUnpackExtensionChanged(params: any) {
this.dispatchEvent({type: 'gbufferUnpackExtensionChanged', ...params})
}
render(scene: IScene, renderToScreen?: boolean): void {
const cbf = this.screenPass.clipBackgroundForce
if (this.rgbm) {
const val = !scene.background && !scene.backgroundColor
if (val !== cbf) this.screenPass.clipBackgroundForce = val
}
super.render(scene, renderToScreen)
}
}