Browse Source

Depth unpack change, add matDefineBool, and other minor changes.

master
Palash Bansal 2 years ago
parent
commit
91a82b96b3
No account linked to committer's email address

+ 8
- 4
src/plugins/pipeline/DepthBufferPlugin.ts View File



// @onChange2(DepthBufferPlugin.prototype._createTarget) // @onChange2(DepthBufferPlugin.prototype._createTarget)
// @uiDropdown('Buffer Type', threeConstMappings.TextureDataType.uiConfig) // @uiDropdown('Buffer Type', threeConstMappings.TextureDataType.uiConfig)
readonly bufferType: TextureDataType // cannot be changed after creation (for now)
readonly bufferType: TextureDataType // cannot be changed after creation (for now) todo line 139: unregisterMaterialExtensions, maybe because the priority is not set so its added at the end?


// @uiToggle() // @uiToggle()
// @onChange2(DepthBufferPlugin.prototype._createTarget) // @onChange2(DepthBufferPlugin.prototype._createTarget)


unpackExtension: MaterialExtension = { unpackExtension: MaterialExtension = {
shaderExtender: (shader)=>{ shaderExtender: (shader)=>{
const includes = ['depth_buffer_unpack', 'gbuffer_unpack', 'packing'] as const
const include = includes.find(i=>shader.fragmentShader.includes(`#include <${i}>`))
shader.fragmentShader = shaderReplaceString(shader.fragmentShader, shader.fragmentShader = shaderReplaceString(shader.fragmentShader,
'#include <packing>',
'\n' + DepthBufferUnpack + '\n', {append: true})
`#include <${include}>`,
'\n' + DepthBufferUnpack + '\n', {append: include === 'packing'})
}, },
extraUniforms: { extraUniforms: {
tDepthBuffer: ()=>({value: this.target?.texture}), tDepthBuffer: ()=>({value: this.target?.texture}),


if (this.isPrimaryGBuffer) { if (this.isPrimaryGBuffer) {
this._viewer.renderManager.gbufferTarget = this.target this._viewer.renderManager.gbufferTarget = this.target
this._viewer.renderManager.gbufferUnpackExtension = this.unpackExtension
this._viewer.renderManager.screenPass.material.registerMaterialExtensions([this.unpackExtension]) this._viewer.renderManager.screenPass.material.registerMaterialExtensions([this.unpackExtension])
this._isPrimaryGBufferSet = true this._isPrimaryGBufferSet = true
} }
this.texture = undefined this.texture = undefined
if (this._isPrimaryGBufferSet) { // using a separate flag as when isPrimaryGBuffer is changed, we cannot check it. if (this._isPrimaryGBufferSet) { // using a separate flag as when isPrimaryGBuffer is changed, we cannot check it.
this._viewer.renderManager.gbufferTarget = undefined this._viewer.renderManager.gbufferTarget = undefined
// this._viewer.renderManager.screenPass.material.unregisterMaterialExtensions([this.unpackExtension]) // todo
this._viewer.renderManager.gbufferUnpackExtension = undefined
// this._viewer.renderManager.screenPass.material.unregisterMaterialExtensions([this.unpackExtension]) // todo this has an issue
this._isPrimaryGBufferSet = false this._isPrimaryGBufferSet = false
} }
} }

+ 2
- 1
src/plugins/pipeline/FrameFadePlugin.ts View File

}) })
this._pass.fadeTimeState = Math.max(duration, this._pass.fadeTimeState) this._pass.fadeTimeState = Math.max(duration, this._pass.fadeTimeState)
this._pass.fadeTime = this._pass.fadeTimeState this._pass.fadeTime = this._pass.fadeTimeState
this._pass.toSaveFrame = true
if (this._pass.fadeTimeState < 500) // only save if very near the end
this._pass.toSaveFrame = true
// this._pass.passObject.enabled = true // this._pass.passObject.enabled = true
this.setDirty() this.setDirty()
await timeout(duration) await timeout(duration)

+ 6
- 2
src/plugins/pipeline/GBufferPlugin.ts View File



unpackExtension: MaterialExtension = { unpackExtension: MaterialExtension = {
shaderExtender: (shader)=>{ shaderExtender: (shader)=>{
const includes = ['gbuffer_unpack', 'packing'] as const
const include = includes.find(i=>shader.fragmentShader.includes(`#include <${i}>`))
shader.fragmentShader = shaderReplaceString(shader.fragmentShader, shader.fragmentShader = shaderReplaceString(shader.fragmentShader,
'#include <packing>',
'\n' + GBufferUnpack + '\n', {append: true})
`#include <${include}>`,
'\n' + GBufferUnpack + '\n', {append: include === 'packing'})
}, },
extraUniforms: { extraUniforms: {
tNormalDepth: ()=>({value: this.normalDepthTexture}), tNormalDepth: ()=>({value: this.normalDepthTexture}),


if (this.isPrimaryGBuffer) { if (this.isPrimaryGBuffer) {
this._viewer.renderManager.gbufferTarget = this.target this._viewer.renderManager.gbufferTarget = this.target
this._viewer.renderManager.gbufferUnpackExtension = this.unpackExtension
this._viewer.renderManager.screenPass.material.registerMaterialExtensions([this.unpackExtension]) this._viewer.renderManager.screenPass.material.registerMaterialExtensions([this.unpackExtension])
this._isPrimaryGBufferSet = true this._isPrimaryGBufferSet = true
} }
this.textures = [] this.textures = []
if (this._isPrimaryGBufferSet) { // using a separate flag as when isPrimaryGBuffer is changed, we cannot check it. if (this._isPrimaryGBufferSet) { // using a separate flag as when isPrimaryGBuffer is changed, we cannot check it.
this._viewer.renderManager.gbufferTarget = undefined this._viewer.renderManager.gbufferTarget = undefined
this._viewer.renderManager.gbufferUnpackExtension = undefined
// this._viewer.renderManager.screenPass.material.unregisterMaterialExtensions([this.unpackExtension]) // todo // this._viewer.renderManager.screenPass.material.unregisterMaterialExtensions([this.unpackExtension]) // todo
this._isPrimaryGBufferSet = false this._isPrimaryGBufferSet = false
} }

+ 5
- 0
src/plugins/pipeline/ProgressivePlugin.ts View File

readonly passId = 'progressive' readonly passId = 'progressive'
public static readonly PluginType = 'ProgressivePlugin' public static readonly PluginType = 'ProgressivePlugin'


/**
* Different targets for different render cameras.
* Need to save them all here since we need them in the next frame.
* @protected
*/
protected _targets = new Map<string, ProgressivePluginTarget>() protected _targets = new Map<string, ProgressivePluginTarget>()


@serialize() @uiInput('Frame count') maxFrameCount: number @serialize() @uiInput('Frame count') maxFrameCount: number

+ 4
- 3
src/plugins/postprocessing/TonemapPlugin.ts View File

import {glsl, onChange, serialize} from 'ts-browser-helpers' import {glsl, onChange, serialize} from 'ts-browser-helpers'
import {IMaterial} from '../../core' import {IMaterial} from '../../core'
import {updateBit} from '../../utils' import {updateBit} from '../../utils'
import {matDefine, uniform} from '../../three'
import {uniform} from '../../three'
import Uncharted2ToneMappingShader from './shaders/Uncharted2ToneMapping.glsl' import Uncharted2ToneMappingShader from './shaders/Uncharted2ToneMapping.glsl'
import TonemapShader from './shaders/TonemapPlugin.pars.glsl' import TonemapShader from './shaders/TonemapPlugin.pars.glsl'
import TonemapShaderPatch from './shaders/TonemapPlugin.patch.glsl' import TonemapShaderPatch from './shaders/TonemapPlugin.patch.glsl'
import {AScreenPassExtensionPlugin} from './AScreenPassExtensionPlugin' import {AScreenPassExtensionPlugin} from './AScreenPassExtensionPlugin'
import {GBufferUpdaterContext} from '../pipeline/GBufferPlugin' import {GBufferUpdaterContext} from '../pipeline/GBufferPlugin'
import {matDefineBool} from '../../three/utils/decorators'


// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
export const Uncharted2Tonemapping: ToneMapping = CustomToneMapping export const Uncharted2Tonemapping: ToneMapping = CustomToneMapping
@serialize() toneMapping: ToneMapping = ACESFilmicToneMapping @serialize() toneMapping: ToneMapping = ACESFilmicToneMapping


@uiToggle('Tonemap Background', (t: TonemapPlugin)=>({hidden: ()=>!t._viewer?.renderManager.gbufferTarget})) @uiToggle('Tonemap Background', (t: TonemapPlugin)=>({hidden: ()=>!t._viewer?.renderManager.gbufferTarget}))
@matDefine('TONEMAP_BACKGROUND', undefined, true, TonemapPlugin.prototype.setDirty, (v)=>v ? '1' : '0', (v) => v !== '0')
@matDefineBool('TONEMAP_BACKGROUND', undefined, true, TonemapPlugin.prototype.setDirty)
@serialize() tonemapBackground = true @serialize() tonemapBackground = true


// todo handle legacy deserialize // todo handle legacy deserialize
return super.fromJSON(data, meta) return super.fromJSON(data, meta)
} }


// TODO: add gBufferData or just tonemapEnabled to the scene material UI with an extension
// TODO: add gBufferData or just tonemapEnabled to the scene material UI with an extension like bloom
updateGBufferFlags(data: Vector4, c: GBufferUpdaterContext): void { updateGBufferFlags(data: Vector4, c: GBufferUpdaterContext): void {
const x = (c.material.userData.gBufferData?.tonemapEnabled ?? c.material?.userData.postTonemap) === false ? 0 : 1 const x = (c.material.userData.gBufferData?.tonemapEnabled ?? c.material?.userData.postTonemap) === false ? 0 : 1
data.w = updateBit(data.w, 1, x) // 2nd Bit data.w = updateBit(data.w, 1, x) // 2nd Bit

+ 2
- 1
src/rendering/RenderManager.ts View File

import { import {
BaseEvent,
Color, Color,
FloatType, FloatType,
HalfFloatType, HalfFloatType,


@serializable('RenderManager') @serializable('RenderManager')
@uiFolderContainer('Render Manager') @uiFolderContainer('Render Manager')
export class RenderManager extends RenderTargetManager<IRenderManagerEvent, IRenderManagerEventTypes> implements IShaderPropertiesUpdater, IRenderManager {
export class RenderManager<TEvent extends BaseEvent = IRenderManagerEvent, TEventTypes extends string = IRenderManagerEventTypes> extends RenderTargetManager<IRenderManagerEvent|TEvent, IRenderManagerEventTypes|TEventTypes> implements IShaderPropertiesUpdater, IRenderManager {
private readonly _isWebGL2: boolean private readonly _isWebGL2: boolean
private readonly _composer: EffectComposer2 private readonly _composer: EffectComposer2
private readonly _context: WebGLRenderingContext private readonly _context: WebGLRenderingContext

+ 22
- 2
src/three/utils/decorators.ts View File

} }


/** /**
*
* @param customDefines - object for setting define value (like ShaderMaterial.defines), otherwise this.material.defines is taken
* Decorator to create a three.js style define in this or this.material and bind to a property.
* see also - {@link matDefineBool}
* @param key - define name * @param key - define name
* @param customDefines - object for setting define value (like ShaderMaterial.defines), otherwise this.material.defines is taken
* @param thisMat - access this.defines instead of this.material.defines * @param thisMat - access this.defines instead of this.material.defines
* @param onChange - function to call when the value changes. The function is called with the following parameters: [key, newVal]. Note: needsUpdate is set to true for this/material if onChange is not provided.
* @param processVal - function that processes the value before setting it.
* @param invProcessVal - function that processes the value before returning it.
*/ */
export function matDefine(key?: string|symbol, customDefines?: any, thisMat = false, onChange?: (...args: any[]) => any, processVal?: (newVal: any)=>any, invProcessVal?: (val:any)=>any): PropertyDecorator { export function matDefine(key?: string|symbol, customDefines?: any, thisMat = false, onChange?: (...args: any[]) => any, processVal?: (newVal: any)=>any, invProcessVal?: (val:any)=>any): PropertyDecorator {
// backing up properties as values are different when called again, no idea why. // backing up properties as values are different when called again, no idea why.
set(newVal: any) { set(newVal: any) {
const {t, p} = getTarget(thisMat ? this : this.material) const {t, p} = getTarget(thisMat ? this : this.material)
if (processVal) newVal = processVal(newVal) if (processVal) newVal = processVal(newVal)
else if (typeof newVal === 'boolean') { // just in case
console.error('Boolean values are not supported for defines. Use @matDefineBool instead.')
newVal = newVal ? '1' : '0'
}
safeSetProperty(t, p, newVal, true) safeSetProperty(t, p, newVal, true)
if (newVal === undefined) delete t[p] if (newVal === undefined) delete t[p]
if (onChange && typeof onChange === 'function') { if (onChange && typeof onChange === 'function') {
} }
} }


/**
* Same as {@link matDefine} but for boolean values. It sets the value to '1' or '0'/undefined.
* @param key - define name
* @param customDefines - object for setting define value (like ShaderMaterial.defines), otherwise this.material.defines is taken
* @param thisMat - access this.defines instead of this.material.defines
* @param onChange - function to call when the value changes. If a string, it is used as a property name in `this` and called. If a function, it is called. The function is called with the following parameters: key, newVal
* @param deleteOnFalse - sets to undefined instead of '0' when false
*/
export function matDefineBool(key?: string|symbol, customDefines?: any, thisMat = false, onChange?: (...args: any[]) => any, deleteOnFalse = false): PropertyDecorator {
return matDefine(key, customDefines, thisMat, onChange, (v: any)=>v ? '1' : deleteOnFalse ? undefined : '0', (v: any)=>v && v !== '0')
}

/** /**
* Binds a property to a value in an object. If the object is a string, it is used as a property name in `this`. * Binds a property to a value in an object. If the object is a string, it is used as a property name in `this`.
* @param obj - object to bind to. If a string, it is used as a property name in `this`. If a function, it is called and the result is used as the object/string. * @param obj - object to bind to. If a string, it is used as a property name in `this`. If a function, it is called and the result is used as the object/string.

+ 14
- 2
src/viewer/ViewerRenderManager.ts View File

import {IRenderTarget, RenderManager} from '../rendering' import {IRenderTarget, RenderManager} from '../rendering'
import {HalfFloatType, LinearMipMapLinearFilter, NoColorSpace, RGBM16ColorSpace, UnsignedByteType} from 'three' import {HalfFloatType, LinearMipMapLinearFilter, NoColorSpace, RGBM16ColorSpace, UnsignedByteType} from 'three'
import {IRenderManagerOptions} from '../core'
import {IRenderManagerEvent, IRenderManagerOptions} from '../core'
import {ExtendedRenderPass, ScreenPass, TViewerScreenShader} from '../postprocessing' import {ExtendedRenderPass, ScreenPass, TViewerScreenShader} from '../postprocessing'
import {uiFolderContainer} from 'uiconfig.js' import {uiFolderContainer} from 'uiconfig.js'
import {MaterialExtension} from '../materials'
import {onChange3} from 'ts-browser-helpers'


export interface ViewerRenderManagerOptions extends IRenderManagerOptions { export interface ViewerRenderManagerOptions extends IRenderManagerOptions {
rgbm?: boolean, rgbm?: boolean,
} }


@uiFolderContainer('Render Manager') @uiFolderContainer('Render Manager')
export class ViewerRenderManager extends RenderManager {
export class ViewerRenderManager extends RenderManager<IRenderManagerEvent, 'gbufferUnpackExtensionChanged'> {
readonly rgbm: boolean readonly rgbm: boolean
readonly msaa: boolean | number readonly msaa: boolean | number
readonly depthBuffer: boolean readonly depthBuffer: boolean
* Reference to the gbuffer target, if it exists. This can be set by plugins like {@link DepthBufferPlugin}, {@link GBufferPlugin} * Reference to the gbuffer target, if it exists. This can be set by plugins like {@link DepthBufferPlugin}, {@link GBufferPlugin}
*/ */
gbufferTarget: IRenderTarget | undefined 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.
*/
@onChange3(ViewerRenderManager.prototype._gbufferUnpackExtensionChanged)
gbufferUnpackExtension: MaterialExtension | undefined

private _gbufferUnpackExtensionChanged(params: any) {
this.dispatchEvent({type: 'gbufferUnpackExtensionChanged', ...params})
}


} }

Loading…
Cancel
Save