| @@ -2,9 +2,24 @@ import {IPassID, IPipelinePass} from '../../postprocessing' | |||
| import {AViewerPluginSync, ISerializedConfig, ThreeViewer} from '../../viewer' | |||
| import {AnyFunction, serialize} from 'ts-browser-helpers' | |||
| import {SerializationMetaType} from '../../utils' | |||
| import {uiConfig, uiToggle} from 'uiconfig.js' | |||
| export abstract class PipelinePassPlugin<T extends IPipelinePass, TPassId extends IPassID, TEvent extends string, TViewer extends ThreeViewer=ThreeViewer> extends AViewerPluginSync<TEvent, TViewer> { | |||
| abstract passId: TPassId | |||
| @serialize() | |||
| @uiToggle('Enabled') | |||
| get enabled(): boolean { | |||
| return this._pass?.enabled || this._enabledTemp | |||
| } | |||
| set enabled(value: boolean) { | |||
| if (this._pass) this._pass.enabled = value | |||
| this._enabledTemp = value | |||
| } | |||
| @uiConfig() | |||
| @serialize('pass') | |||
| protected _pass?: T | |||
| abstract createPass(v:TViewer):T | |||
| @@ -17,15 +32,6 @@ export abstract class PipelinePassPlugin<T extends IPipelinePass, TPassId extend | |||
| protected _beforeRender(): boolean {return this._pass?.enabled && this.enabled || false} | |||
| private _enabledTemp = true // to save enabled state when pass is not yet created | |||
| @serialize() | |||
| get enabled(): boolean { | |||
| return this._pass?.enabled || this._enabledTemp | |||
| } | |||
| set enabled(value: boolean) { | |||
| if (this._pass) this._pass.enabled = value | |||
| this._enabledTemp = value | |||
| } | |||
| constructor() { | |||
| super() | |||
| @@ -13,11 +13,14 @@ import {GBufferRenderPass} from '../../postprocessing' | |||
| import {ThreeViewer} from '../../viewer' | |||
| import {IShaderPropertiesUpdater} from '../../materials' | |||
| import {PipelinePassPlugin} from '../base/PipelinePassPlugin' | |||
| import {uiFolderContainer, uiImage} from 'uiconfig.js' | |||
| export type DepthBufferPluginEventTypes = '' | |||
| // type DepthBufferPluginTarget = WebGLMultipleRenderTargets | WebGLRenderTarget | |||
| export type DepthBufferPluginTarget = WebGLRenderTarget | |||
| export type DepthBufferPluginPass = GBufferRenderPass<'depth', DepthBufferPluginTarget> | |||
| @uiFolderContainer('Depth Buffer Plugin') | |||
| export class DepthBufferPlugin | |||
| extends PipelinePassPlugin<DepthBufferPluginPass, 'depth', DepthBufferPluginEventTypes> | |||
| implements IShaderPropertiesUpdater { | |||
| @@ -26,7 +29,9 @@ export class DepthBufferPlugin | |||
| public static readonly PluginType = 'DepthBufferPlugin' | |||
| target?: DepthBufferPluginTarget | |||
| texture?: Texture | |||
| @uiImage('Depth Buffer' /* {readOnly: true}*/) texture?: Texture | |||
| readonly material: MeshDepthMaterial = new MeshDepthMaterial({ | |||
| depthPacking: BasicDepthPacking, | |||
| blending: NoBlending, | |||
| @@ -39,10 +44,10 @@ export class DepthBufferPlugin | |||
| depthBuffer: true, | |||
| samples: v.renderManager.composerTarget.samples || 0, | |||
| type: this.bufferType, | |||
| // magFilter: NearestFilter, | |||
| // minFilter: NearestFilter, | |||
| // generateMipmaps: false, | |||
| // encoding: LinearEncoding, | |||
| // magFilter: NearestFilter, | |||
| // minFilter: NearestFilter, | |||
| // generateMipmaps: false, | |||
| // encoding: LinearEncoding, | |||
| }) | |||
| this.texture = this.target.texture | |||
| this.texture.name = 'depthBuffer' | |||
| @@ -61,9 +66,11 @@ export class DepthBufferPlugin | |||
| constructor( | |||
| public readonly bufferType: TextureDataType = UnsignedByteType, | |||
| public readonly isPrimaryGBuffer = false | |||
| public readonly isPrimaryGBuffer = false, | |||
| enabled = true, | |||
| ) { | |||
| super() | |||
| this.enabled = enabled | |||
| } | |||
| onRemove(viewer: ThreeViewer): void { | |||
| @@ -22,11 +22,13 @@ import {ThreeViewer} from '../../viewer' | |||
| import {IShaderPropertiesUpdater} from '../../materials' | |||
| import {PipelinePassPlugin} from '../base/PipelinePassPlugin' | |||
| import type {IMaterial, PhysicalMaterial} from '../../core' | |||
| import {uiFolderContainer, uiImage} from 'uiconfig.js' | |||
| export type NormalBufferPluginEventTypes = '' | |||
| // type NormalBufferPluginTarget = WebGLMultipleRenderTargets | WebGLRenderTarget | |||
| export type NormalBufferPluginTarget = WebGLRenderTarget | |||
| export type NormalBufferPluginPass = GBufferRenderPass<'normal', NormalBufferPluginTarget> | |||
| @uiFolderContainer('Normal Buffer Plugin') | |||
| export class NormalBufferPlugin | |||
| extends PipelinePassPlugin<NormalBufferPluginPass, 'normal', NormalBufferPluginEventTypes> | |||
| implements IShaderPropertiesUpdater { | |||
| @@ -35,7 +37,7 @@ export class NormalBufferPlugin | |||
| public static readonly PluginType = 'NormalBufferPlugin' | |||
| target?: NormalBufferPluginTarget | |||
| texture?: Texture | |||
| @uiImage('Normal Buffer' /* {readOnly: true}*/) texture?: Texture | |||
| readonly material: MeshNormalMaterial = new MeshNormalMaterial2({ | |||
| blending: NoBlending, | |||
| }) | |||
| @@ -68,8 +70,10 @@ export class NormalBufferPlugin | |||
| constructor( | |||
| public readonly bufferType: TextureDataType = HalfFloatType, | |||
| enabled = true, | |||
| ) { | |||
| super() | |||
| this.enabled = enabled | |||
| } | |||
| onRemove(viewer: ThreeViewer): void { | |||
| @@ -4,18 +4,22 @@ import {createDiv, createStyles, getOrCall, onChange, ValOrFunc} from 'ts-browse | |||
| import {SRGBColorSpace, Vector4, WebGLRenderTarget} from 'three' | |||
| import styles from './RenderTargetPreviewPlugin.css' | |||
| import {CustomContextMenu} from '../../utils' | |||
| import {uiFolderContainer, uiToggle} from 'uiconfig.js' | |||
| @uiFolderContainer('Render Target Preview Plugin') | |||
| export class RenderTargetPreviewPlugin<TEvent extends string> extends AViewerPluginSync<TEvent> { | |||
| static readonly PluginType = 'RenderTargetPreviewPlugin' | |||
| @uiToggle('Enabled') | |||
| @onChange(RenderTargetPreviewPlugin.prototype.refreshUi) enabled = true | |||
| toJSON: any = null | |||
| mainDiv: HTMLDivElement = createDiv({id: 'RenderTargetPreviewPluginContainer'}) | |||
| mainDiv: HTMLDivElement = createDiv({id: 'RenderTargetPreviewPluginContainer', addToBody: false}) | |||
| stylesheet?: HTMLStyleElement | |||
| constructor() { | |||
| constructor(enabled = true) { | |||
| super() | |||
| this.enabled = enabled | |||
| } | |||
| targetBlocks: { | |||
| @@ -76,9 +80,11 @@ export class RenderTargetPreviewPlugin<TEvent extends string> extends AViewerPlu | |||
| } | |||
| addTarget(target: ValOrFunc<IRenderTarget|undefined>, name: string, transparent = false, originalColorSpace = false, visible = true): this { | |||
| if (!target) return this | |||
| const div = document.createElement('div') | |||
| const targetDef = {target, name, transparent, div, originalColorSpace, visible} | |||
| div.classList.add('RenderTargetPreviewPluginTarget') | |||
| if (!targetDef.visible) div.classList.add('RenderTargetPreviewPluginCollapsed') | |||
| const header = document.createElement('div') | |||
| header.classList.add('RenderTargetPreviewPluginTargetHeader') | |||
| header.innerText = name | |||
| @@ -43,7 +43,7 @@ export class TweakpaneUiPlugin extends UiConfigRendererTweakpane implements IVie | |||
| private _plugins: IViewerPlugin[] = [] | |||
| setupPlugins<T extends IViewerPlugin>(...plugins: Class<T>[]): void { | |||
| setupPlugins(...plugins: Class<IViewerPlugin>[]): void { | |||
| plugins.forEach(plugin => this.setupPluginUi(plugin)) | |||
| } | |||
| @@ -2,9 +2,14 @@ import {Color, Material, WebGLMultipleRenderTargets, WebGLRenderTarget} from 'th | |||
| import {RenderPass} from 'three/examples/jsm/postprocessing/RenderPass.js' | |||
| import {IPassID, IPipelinePass} from './Pass' | |||
| import {ICamera, IMaterial, IRenderManager, IScene, IWebGLRenderer, PhysicalMaterial} from '../core' | |||
| import {uiFolderContainer, UiObjectConfig, uiToggle} from 'uiconfig.js' | |||
| export class GBufferRenderPass<TP extends IPassID, T extends WebGLMultipleRenderTargets | WebGLRenderTarget> extends RenderPass implements IPipelinePass<TP> { // todo: extend from jittered? | |||
| @uiFolderContainer<GBufferRenderPass>((c)=>c.passId + ' Render Pass') | |||
| export class GBufferRenderPass<TP extends IPassID=IPassID, T extends WebGLMultipleRenderTargets | WebGLRenderTarget=WebGLMultipleRenderTargets | WebGLRenderTarget> extends RenderPass implements IPipelinePass<TP> { // todo: extend from jittered? | |||
| readonly isGBufferRenderPass = true | |||
| uiConfig: UiObjectConfig | |||
| @uiToggle('Enabled') enabled = true | |||
| scene?: IScene | |||
| before?: IPassID[] | |||
| @@ -32,7 +32,7 @@ import { | |||
| upgradeWebGLRenderer, | |||
| } from '../core' | |||
| import {base64ToArrayBuffer, canvasFlipY, Class, onChange2, serializable, serialize, ValOrArr} from 'ts-browser-helpers' | |||
| import {uiConfig, uiFolderContainer, uiMonitor, uiSlider, uiToggle} from 'uiconfig.js' | |||
| import {uiButton, uiConfig, uiFolderContainer, uiMonitor, uiSlider, uiToggle} from 'uiconfig.js' | |||
| import {generateUUID, textureDataToImageData} from '../three' | |||
| import {BlobExt, EXRExporter2} from '../assetmanager' | |||
| @@ -74,6 +74,7 @@ export class RenderManager extends RenderTargetManager<IRenderManagerEvent, IRen | |||
| @onChange2(RenderManager.prototype.rebuildPipeline) | |||
| public autoBuildPipeline = true | |||
| @uiButton('Rebuild Pipeline') | |||
| rebuildPipeline(setDirty = true): void { | |||
| this._passesNeedsUpdate = true | |||
| if (setDirty) this._updated({change: 'rebuild'}) | |||