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.
171 lines (146 loc) • 6.4 kB
text/typescript
import {PartialRecord} from 'ts-browser-helpers'
import {Blending, Clock, ShaderMaterial, Texture, Vector2, Vector4, WebGLRenderer, WebGLRenderTarget} from 'three'
import {CreateRenderTargetOptions, IRenderTarget, RenderTargetManager} from '../rendering'
import {IShaderPropertiesUpdater} from '../materials'
import {EffectComposer2, IPassID, IPipelinePass} from '../postprocessing'
import {IScene} from './IScene'
import {BlobExt} from '../assetmanager'
export type TThreeRendererMode = 'shadowMapRender' | 'backgroundRender' | 'sceneRender' | 'opaqueRender' | 'transparentRender' | 'transmissionRender' | 'mainRenderPass' | 'screenSpaceRendering'
export type TThreeRendererModeUserData = PartialRecord<TThreeRendererMode, boolean>
export interface IAnimationLoopEvent {
renderer: IWebGLRenderer
deltaTime: number
time: number
xrFrame?: XRFrame
}
export interface IRenderManagerUpdateEvent {
change?: 'registerPass' | 'unregisterPass' | 'useLegacyLights' | 'passRefresh' | 'size' | 'rebuild' | string
data?: any
pass?: IPipelinePass
}
export interface IRenderManagerEventMap {
animationLoop: IAnimationLoopEvent
update: IRenderManagerUpdateEvent
resize: object
contextRestored: object
contextLost: {
event: WebGLContextEvent
}
preRender: {
scene: IScene
renderToScreen: boolean
}
postRender: {
scene: IScene
renderToScreen: boolean
}
}
export interface RendererBlitOptions {
source?: Texture,
viewport?: Vector4,
material?: ShaderMaterial,
clear?: boolean,
respectColorSpace?: boolean,
blending?: Blending,
transparent?: boolean,
opacity?: number,
blendAlpha?: number
}
export interface IRenderManager<TE extends IRenderManagerEventMap = IRenderManagerEventMap> extends RenderTargetManager<TE>, IShaderPropertiesUpdater{
readonly renderer: IWebGLRenderer
readonly needsRender: boolean
rebuildPipeline(setDirty?: boolean): void
setSize(width: number, height: number): void
render(scene: IScene): void
reset(): void
resetShadows(): void
refreshPasses(): void
registerPass(pass: IPipelinePass, replaceId?: boolean): void
unregisterPass(pass: IPipelinePass): void
readonly frameCount: number
readonly totalFrameCount: number
pipeline: IPassID[]
composer: EffectComposer2
readonly passes: IPipelinePass[]
readonly isWebGL2: boolean
readonly composerTarget: IRenderTarget
readonly renderSize: Vector2
renderScale: number
readonly context: WebGLRenderingContext
useLegacyLights: boolean
webglRenderer: WebGLRenderer
clock: Clock
blit(destination: IRenderTarget|undefined|null, options?: RendererBlitOptions): void
clearColor({r, g, b, a, target, depth, stencil, viewport}:
{r?: number, g?: number, b?: number, a?: number, target?: IRenderTarget, depth?: boolean, stencil?: boolean, viewport?: Vector4}): void
renderTargetToDataUrl(target: WebGLRenderTarget, mimeType?: string, quality?: number): string
renderTargetToBuffer(target: WebGLRenderTarget): Uint8Array|Uint16Array|Float32Array
exportRenderTarget(target: WebGLRenderTarget, mimeType?: 'auto'|string, textureIndex?: number): BlobExt
}
export interface IRenderManagerOptions {
canvas: HTMLCanvasElement,
alpha?: boolean, // default = true
targetOptions?: CreateRenderTargetOptions
rgbm?: boolean,
msaa?: boolean | number,
depthBuffer?: boolean,
renderScale?: number,
powerPreference?: WebGLPowerPreference,
}
export interface IWebGLRenderer<TManager extends IRenderManager=IRenderManager> extends WebGLRenderer {
renderManager: TManager
userData: TThreeRendererModeUserData & {
// eslint-disable-next-line @typescript-eslint/naming-convention
__isIWebGLRenderer: true
[key: string]: any
}
renderWithModes(ud: TThreeRendererModeUserData, render: ()=>void): void
// legacy
/**
* @deprecated use {@link renderManager} instead
*/
baseRenderer?: IRenderManager
}
export function upgradeWebGLRenderer<TManager extends IRenderManager=IRenderManager>(this: IWebGLRenderer<TManager>, manager: TManager): IWebGLRenderer<TManager> {
if (this.userData?.__isIWebGLRenderer) return this
// eslint-disable-next-line @typescript-eslint/naming-convention
if (!this.userData) this.userData = {__isIWebGLRenderer: true}
this.userData.__isIWebGLRenderer = true
if (!this.renderWithModes) this.renderWithModes = renderWithModes
this.renderManager = manager
// legacy
if (!this.baseRenderer) {
Object.defineProperty(this, 'baseRenderer', {
get: ()=>{
console.warn('IWebGLRenderer.baseRenderer is deprecated, use IWebGLRenderer.renderManager instead')
return this.renderManager
},
})
}
return this
}
function renderWithModes(this: IWebGLRenderer, ud: TThreeRendererModeUserData, render: ()=>void) {
const rud = this.userData
const {backgroundRender, transparentRender, shadowMapRender, mainRenderPass, opaqueRender, transmissionRender, sceneRender, screenSpaceRendering} = rud
if (ud.backgroundRender !== undefined) rud.backgroundRender = ud.backgroundRender
if (ud.transparentRender !== undefined) rud.transparentRender = ud.transparentRender
if (ud.shadowMapRender !== undefined) rud.shadowMapRender = ud.shadowMapRender
if (ud.mainRenderPass !== undefined) rud.mainRenderPass = ud.mainRenderPass
if (ud.opaqueRender !== undefined) rud.opaqueRender = ud.opaqueRender
if (ud.sceneRender !== undefined) rud.sceneRender = ud.sceneRender
if (ud.transmissionRender !== undefined) rud.transmissionRender = ud.transmissionRender
if (ud.screenSpaceRendering !== undefined) rud.screenSpaceRendering = ud.screenSpaceRendering
render()
rud.backgroundRender = backgroundRender
rud.transparentRender = transparentRender
rud.shadowMapRender = shadowMapRender
rud.mainRenderPass = mainRenderPass
rud.opaqueRender = opaqueRender
rud.sceneRender = sceneRender
rud.transmissionRender = transmissionRender
rud.screenSpaceRendering = screenSpaceRendering
}
/**
* @deprecated renamed to {@link renderWithModes}, use {@link IWebGLRenderer.renderWithModes}
*/
export const setThreeRendererMode = renderWithModes