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.
704 lines • 31.5 kB
JavaScript
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;
};
var RenderManager_1;
import { AddEquation, Color, ConstantAlphaFactor, CustomBlending, FloatType, HalfFloatType, NoBlending, NoColorSpace, NormalBlending, NoToneMapping, OneMinusConstantAlphaFactor, PCFShadowMap, Vector2, Vector4, WebGLRenderer, } from 'three';
import { EffectComposer2, sortPasses } from '../postprocessing';
import { RenderTargetManager } from './RenderTargetManager';
import { upgradeWebGLRenderer, } from '../core';
import { base64ToArrayBuffer, canvasFlipY, getOrCall, onChange2, serializable, serialize, } from 'ts-browser-helpers';
import { uiButton, uiConfig, uiDropdown, uiFolderContainer, uiMonitor, uiSlider, uiToggle } from 'uiconfig.js';
import { bindToValue, generateUUID, textureDataToImageData } from '../three';
import { EXRExporter2 } from '../assetmanager';
let RenderManager = RenderManager_1 = class RenderManager extends RenderTargetManager {
get renderScale() {
return this._renderScale;
}
set renderScale(value) {
if (value !== this._renderScale) {
this._renderScale = value;
this.setSize(undefined, undefined, true);
}
}
_shadowMapTypeChanged() {
this.resetShadows();
this.reset();
}
get renderer() { return this._renderer; }
rebuildPipeline(setDirty = true) {
this._passesNeedsUpdate = true;
if (setDirty)
this._updated({ change: 'rebuild' });
}
/**
* Regenerates the render pipeline by resolving dependencies and sorting the passes.
* This is called automatically when the passes are changed.
*/
_refreshPipeline() {
if (!this.autoBuildPipeline)
return this._pipeline;
const ps = this._passes;
try {
this._pipeline = sortPasses(ps);
}
catch (e) {
console.error('RenderManager: Unable to sort rendering passes', e);
}
return this._pipeline;
}
_animationLoop(time, frame) {
const deltaTime = time - this._lastTime;
this._lastTime = time;
this.frameWaitTime -= deltaTime;
if (this.frameWaitTime > 0)
return;
this.frameWaitTime = 0;
this.dispatchEvent({ type: 'animationLoop', deltaTime, time, renderer: this._renderer, xrFrame: frame });
}
constructor({ canvas, alpha = true, renderScale = 1, targetOptions }) {
super();
this._renderSize = new Vector2(512, 512); // this is updated automatically.
this._renderScale = 1.;
this._passes = [];
this._pipeline = [];
this._passesNeedsUpdate = true;
this._frameCount = 0;
this._lastTime = 0;
this._totalFrameCount = 0;
/**
* Use total frame count, if this is set to true, then frameCount won't be reset when the viewer is set to dirty.
* Which will generate different random numbers for each frame during postprocessing steps. With TAA set properly, this will give a smoother result.
*/
this.stableNoise = false;
this.frameWaitTime = 0; // time to wait before next frame // used by canvas recorder //todo/
this._dirty = true;
/**
* Set autoBuildPipeline = false to be able to set the pipeline manually.
*/
this.autoBuildPipeline = true;
// render(scene: RenderScene): void {
// const camera = scene.activeCamera
// const activeScene = scene.activeScene
// if(!camera) return
// this._renderer.render(scene.threeScene, camera)
// // todo gizmos
// }
/**
* Default value for renderToScreen in {@link render}
*/
this.defaultRenderToScreen = true;
this.onPostFrame = () => {
for (const pass of this._passes) {
if (pass.enabled && pass.onPostFrame)
pass.onPostFrame?.(this);
}
};
this._animationLoop = this._animationLoop.bind(this);
// this._xrPreAnimationLoop = this._xrPreAnimationLoop.bind(this)
this._renderSize = new Vector2(canvas.clientWidth, canvas.clientHeight);
this._renderScale = renderScale;
this._renderer = this._initWebGLRenderer(canvas, alpha, targetOptions?.stencilBuffer ?? false);
this._context = this._renderer.getContext();
this._isWebGL2 = this._renderer.capabilities.isWebGL2;
if (!this._isWebGL2)
console.error('RenderManager: WebGL 1 is not officially supported anymore. Some features may not work.');
this.resetShadows();
const composerTarget = this.createTarget(targetOptions, false);
composerTarget.texture.name = 'EffectComposer.rt1';
this._composer = new EffectComposer2(this._renderer, composerTarget);
// if (animationLoop) this.addEventListener('animationLoop', animationLoop) // todo: from viewer
}
_initWebGLRenderer(canvas, alpha, stencil) {
const renderer = new WebGLRenderer({
canvas,
antialias: false,
alpha,
premultipliedAlpha: false, // todo: see this, maybe use this with rgbm mode.
preserveDrawingBuffer: true,
powerPreference: RenderManager_1.POWER_PREFERENCE,
stencil,
});
// renderer.info.autoReset = false // Not supported by ExtendedRenderPass
// renderer.useLegacyLights = false
renderer.setAnimationLoop(this._animationLoop);
renderer.onContextLost = (event) => {
this.dispatchEvent({ type: 'contextLost', event });
};
renderer.onContextRestore = () => {
// console.log('restored')
this.dispatchEvent({ type: 'contextRestored' });
};
renderer.setSize(this._renderSize.width, this._renderSize.height, false);
renderer.setPixelRatio(this._renderScale);
renderer.toneMapping = NoToneMapping;
renderer.toneMappingExposure = 1;
renderer.outputColorSpace = NoColorSpace; // or SRGBColorSpace
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = PCFShadowMap; // use? THREE.PCFShadowMap. dont use VSM if need ground: https://github.com/mrdoob/three.js/issues/17473
// renderer.shadowMap.type = BasicShadowMap // use? THREE.PCFShadowMap. dont use VSM if need ground: https://github.com/mrdoob/three.js/issues/17473
renderer.shadowMap.autoUpdate = false;
return upgradeWebGLRenderer.call(renderer, this);
}
setSize(width, height, force = false) {
if (!force &&
(width ? Math.abs(width - this._renderSize.width) : 0) +
(height ? Math.abs(height - this._renderSize.height) : 0) < 0.1)
return;
if (width)
this._renderSize.width = width;
if (height)
this._renderSize.height = height;
if (!(this.webglRenderer.xr.enabled && this.webglRenderer.xr.isPresenting)) {
this._renderer.setSize(this._renderSize.width, this._renderSize.height, false);
this._renderer.setPixelRatio(this._renderScale);
}
this._composer.setPixelRatio(this._renderScale, false);
this._composer.setSize(this._renderSize.width, this._renderSize.height);
this.resizeTrackedTargets();
// console.log('setSize', {...this._renderSize}, this._trackedTargets.length)
this.dispatchEvent({ type: 'resize' });
this._updated({ change: 'size', data: this._renderSize.toArray() });
this.reset();
}
render(scene, renderToScreen) {
if (this._passesNeedsUpdate) {
this._refreshPipeline();
this.refreshPasses();
}
for (const pass of this._passes) {
if (pass.enabled && pass.beforeRender)
pass.beforeRender(scene, scene.renderCamera, this);
}
this._composer.renderToScreen = renderToScreen ?? this.defaultRenderToScreen;
this.dispatchEvent({ type: 'preRender', scene, renderToScreen: this._composer.renderToScreen });
this._composer.render();
this.dispatchEvent({ type: 'postRender', scene, renderToScreen: this._composer.renderToScreen });
this._composer.renderToScreen = true;
if (renderToScreen) {
this.incRenderToScreen();
}
this._dirty = false;
}
// todo better name
incRenderToScreen() {
this._frameCount += 1;
this._totalFrameCount += 1;
}
get needsRender() {
if (this.renderSize.x < 1 || this.renderSize.y < 1)
return false;
this._dirty = this._dirty || this._passes.findIndex(value => getOrCall(value.dirty)) >= 0; // todo: check for enabled passes only.
return this._dirty;
}
setDirty(reset = false) {
this._dirty = true;
if (reset)
this.reset();
// do NOT call _updated from here.
}
reset() {
this._frameCount = 0;
this._dirty = true;
// do NOT call _updated from here.
}
resetShadows() {
this._renderer.shadowMap.needsUpdate = true;
}
refreshPasses() {
if (!this._passesNeedsUpdate)
return;
this._passesNeedsUpdate = false;
const p = [];
for (const passId of this._pipeline) {
const a = this._passes.find(value => value.passId === passId);
if (!a) {
console.warn('Unable to find pass: ', passId);
continue;
}
p.push(a);
}
[...this._composer.passes].forEach(p1 => this._composer.removePass(p1));
p.forEach(p1 => this._composer.addPass(p1));
this._updated({ change: 'passRefresh' });
}
dispose(clear = true) {
super.dispose(clear);
this._renderer.dispose();
}
updateShaderProperties(material) {
if (material.uniforms.currentFrameCount)
material.uniforms.currentFrameCount.value = this.frameCount;
if (!this.stableNoise) {
if (material.uniforms.frameCount)
material.uniforms.frameCount.value = this._totalFrameCount;
else
console.warn('RenderManager: no uniform: frameCount');
}
else {
if (material.uniforms.frameCount)
material.uniforms.frameCount.value = this.frameCount;
else
console.warn('RenderManager: no uniform: frameCount');
}
return this;
}
// region Passes
registerPass(pass, replaceId = true) {
if (replaceId) {
for (const pass1 of [...this._passes]) {
if (pass.passId === pass1.passId)
this.unregisterPass(pass1);
}
}
this._passes.push(pass);
pass.onRegister?.(this);
this.rebuildPipeline(false);
this._updated({ change: 'registerPass', pass });
}
unregisterPass(pass) {
const i = this._passes.indexOf(pass);
if (i >= 0) {
pass.onUnregister?.(this);
this._passes.splice(i, 1);
this.rebuildPipeline(false);
this._updated({ change: 'unregisterPass', pass });
}
}
// endregion
// region Getters and Setters
get frameCount() {
return this._frameCount;
}
get totalFrameCount() {
return this._totalFrameCount;
}
resetTotalFrameCount() {
this._totalFrameCount = 0;
}
set pipeline(value) {
this._pipeline = value;
if (this.autoBuildPipeline) {
console.warn('RenderManager: pipeline changed, but autoBuildPipeline is true. This will not have any effect.');
}
this.rebuildPipeline();
}
get pipeline() {
return this._pipeline;
}
get composer() {
return this._composer;
}
get passes() {
return this._passes;
}
get isWebGL2() {
return this._isWebGL2;
}
get composerTarget() {
return this._composer.renderTarget1;
}
get composerTarget2() {
return this._composer.renderTarget2;
}
/**
* The size set in the three.js renderer.
* Final size is renderSize * renderScale
*/
get renderSize() {
return this._renderSize;
}
get context() {
return this._context;
}
/**
* Same as {@link renderer}
*/
get webglRenderer() {
return this._renderer;
}
/**
* @deprecated will be removed in the future
*/
get useLegacyLights() {
return this._renderer.useLegacyLights;
}
set useLegacyLights(v) {
this._renderer.useLegacyLights = v;
this._updated({ change: 'useLegacyLights', data: v });
this.resetShadows();
}
get clock() {
return this._composer.clock;
}
// endregion
// region Utils
/**
* blit - blits a texture to the screen or another render target.
* @param destination - destination target, or screen if undefined or null
* @param source - source Texture
* @param viewport - viewport and scissor
* @param material - override material
* @param clear - clear before blit
* @param respectColorSpace - does color space conversion when reading and writing to the target
* @param blending - Note - Set to NormalBlending if transparent is set to false
* @param transparent
* @param opacity - opacity of the material, if not set, uses the material's opacity
* @param blendAlpha - custom blending factor, if set, overrides blending. The material will use CustomBlending with ConstantAlphaFactor and OneMinusConstantAlphaFactor, useful to blend between textures.
*/
blit(destination, { source, viewport, material, clear = true, respectColorSpace = false, blending = NoBlending, transparent = true, opacity, blendAlpha } = {}) {
const copyPass = !respectColorSpace ? this._composer.copyPass : this._composer.copyPass2;
const { renderToScreen, material: oldMaterial, uniforms: oldUniforms, clear: oldClear } = copyPass;
if (material) {
copyPass.material = material;
}
const oldTransparent = copyPass.material.transparent;
const oldViewport = !destination ? this._renderer.getViewport(new Vector4()) : destination.viewport.clone();
const oldScissor = !destination ? this._renderer.getScissor(new Vector4()) : destination.scissor.clone();
const oldScissorTest = !destination ? this._renderer.getScissorTest() : destination.scissorTest;
const oldAutoClear = this._renderer.autoClear;
const oldTarget = this._renderer.getRenderTarget();
const oldBlending = copyPass.material.blending;
const oldOpacity = copyPass.material.uniforms.opacity?.value ?? 1;
const oldBlendAlpha = copyPass.material.blendAlpha;
const oldBlendSrc = copyPass.material.blendSrc;
const oldBlendDst = copyPass.material.blendDst;
const oldBlendEquation = copyPass.material.blendEquation;
if (viewport) {
if (!destination) {
this._renderer.setViewport(viewport);
this._renderer.setScissor(viewport);
this._renderer.setScissorTest(true);
}
else {
destination.viewport.copy(viewport);
destination.scissor.copy(viewport);
destination.scissorTest = true;
}
}
this._renderer.autoClear = false;
copyPass.material.blending = !transparent ? NormalBlending : blending;
copyPass.uniforms = copyPass.material.uniforms;
copyPass.renderToScreen = false;
copyPass.clear = clear;
copyPass.material.transparent = transparent;
copyPass.material.needsUpdate = true;
if (copyPass.material.uniforms.opacity && opacity !== undefined) {
copyPass.material.uniforms.opacity.value = opacity;
}
if (blendAlpha !== undefined) {
// blendAlpha is custom blending factor
copyPass.material.blending = CustomBlending;
copyPass.material.blendSrc = ConstantAlphaFactor;
copyPass.material.blendDst = OneMinusConstantAlphaFactor;
copyPass.material.blendEquation = AddEquation;
copyPass.material.blendAlpha = blendAlpha;
}
this._renderer.renderWithModes({
sceneRender: true,
opaqueRender: true,
shadowMapRender: false,
backgroundRender: false,
transparentRender: true,
transmissionRender: false,
}, () => {
copyPass.render(this._renderer, destination || null, { texture: source }, 0, false);
});
if (copyPass.material.uniforms.opacity && opacity !== undefined) {
copyPass.material.uniforms.opacity.value = oldOpacity;
}
copyPass.renderToScreen = renderToScreen;
copyPass.clear = oldClear;
copyPass.material.blending = oldBlending;
copyPass.material.blendSrc = oldBlendSrc;
copyPass.material.blendDst = oldBlendDst;
copyPass.material.blendEquation = oldBlendEquation;
copyPass.material.blendAlpha = oldBlendAlpha;
copyPass.material.transparent = oldTransparent;
copyPass.material = oldMaterial;
copyPass.uniforms = oldUniforms;
this._renderer.autoClear = oldAutoClear;
if (viewport) {
if (!destination) {
this._renderer.setViewport(oldViewport);
this._renderer.setScissor(oldScissor);
this._renderer.setScissorTest(oldScissorTest);
}
else {
destination.viewport.copy(oldViewport);
destination.scissor.copy(oldScissor);
destination.scissorTest = oldScissorTest;
}
}
this._renderer.setRenderTarget(oldTarget); // todo: active cubeface etc
}
clearColor({ r, g, b, a, target, depth = true, stencil = true, viewport }) {
const color = this._renderer.getClearColor(new Color());
const alpha = this._renderer.getClearAlpha();
this._renderer.setClearColor(new Color(r ?? color.r, g ?? color.g, b ?? color.b), a ?? alpha);
const lastTarget = this._renderer.getRenderTarget();
const activeCubeFace = this._renderer.getActiveCubeFace();
const activeMipLevel = this._renderer.getActiveMipmapLevel();
const oldViewport = !target ? this._renderer.getViewport(new Vector4()) : target.viewport.clone();
const oldScissor = !target ? this._renderer.getScissor(new Vector4()) : target.scissor.clone();
const oldScissorTest = !target ? this._renderer.getScissorTest() : target.scissorTest;
if (viewport) {
if (!target) {
this._renderer.setViewport(viewport);
this._renderer.setScissor(viewport);
this._renderer.setScissorTest(true);
}
else {
target.viewport.copy(viewport);
target.scissor.copy(viewport);
target.scissorTest = true;
}
}
this._renderer.setRenderTarget(target ?? null);
this._renderer.clear(true, depth, stencil);
if (target && typeof target.clear === 'function') {
// WebGLCubeRenderTarget
target.clear(this._renderer, true, depth, stencil);
}
else {
this._renderer.setRenderTarget(target ?? null);
this._renderer.clear(true, depth, stencil);
}
if (viewport) {
if (!target) {
this._renderer.setViewport(oldViewport);
this._renderer.setScissor(oldScissor);
this._renderer.setScissorTest(oldScissorTest);
}
else {
target.viewport.copy(oldViewport);
target.scissor.copy(oldScissor);
target.scissorTest = oldScissorTest;
}
}
this._renderer.setRenderTarget(lastTarget, activeCubeFace, activeMipLevel);
this._renderer.setClearColor(color, alpha);
}
/**
* Copies a render target to a new/existing canvas element.
* Note: this will clamp the values to [0, 1] and converts to srgb for float and half-float render targets.
* @param target
* @param textureIndex - index of the texture to use in the render target (only in case of multiple render target)
* @param canvas - optional canvas to render to, if not provided a new canvas will be created.
*/
renderTargetToCanvas(target, textureIndex = 0, canvas) {
canvas = canvas ?? document.createElement('canvas');
canvas.width = target.width;
canvas.height = target.height;
const ctx = canvas.getContext('2d');
if (!ctx)
throw new Error('Unable to get 2d context');
const texture = Array.isArray(target.texture) ? target.texture[textureIndex] : target.texture;
const imageData = ctx.createImageData(target.width, target.height, { colorSpace: ['display-p3', 'srgb'].includes(texture.colorSpace) ? texture.colorSpace : undefined });
if (texture.type === HalfFloatType || texture.type === FloatType) {
const buffer = this.renderTargetToBuffer(target, textureIndex);
textureDataToImageData({ data: buffer, width: target.width, height: target.height }, texture.colorSpace, imageData); // this handles converting to srgb
}
else {
// todo: handle rgbm to srgb conversion?
this._renderer.readRenderTargetPixels(target, 0, 0, target.width, target.height, imageData.data, undefined, textureIndex);
}
ctx.putImageData(imageData, 0, 0);
return canvas;
}
/**
* Converts a render target to a png/jpeg data url string.
* Note: this will clamp the values to [0, 1] and converts to srgb for float and half-float render targets.
* @param target
* @param mimeType
* @param quality
* @param textureIndex - index of the texture to use in the render target (only in case of multiple render target)
*/
renderTargetToDataUrl(target, mimeType = 'image/png', quality = 90, textureIndex = 0) {
const texture = Array.isArray(target.texture) ? target.texture[textureIndex] : target.texture;
const canvas = this.renderTargetToCanvas(target, textureIndex);
const string = (texture.flipY ? canvas : canvasFlipY(canvas)).toDataURL(mimeType, quality); // intentionally inverted ternary
canvas.remove();
return string;
}
/**
* Rend pixels from a render target into a new Uint8Array|Uint16Array|Float32Array buffer
* @param target - render target to read from
* @param textureIndex - index of the texture to use in the render target (only in case of multiple render target)
*/
renderTargetToBuffer(target, textureIndex = 0) {
const texture = Array.isArray(target.texture) ? target.texture[textureIndex] : target.texture;
const buffer = texture.type === HalfFloatType ?
new Uint16Array(target.width * target.height * 4) :
texture.type === FloatType ?
new Float32Array(target.width * target.height * 4) :
new Uint8Array(target.width * target.height * 4);
this._renderer.readRenderTargetPixels(target, 0, 0, target.width, target.height, buffer, undefined, textureIndex);
return buffer;
}
/**
* Exports a render target to a blob. The type is automatically picked from exr to png based on the render target.
* @param target - render target to export
* @param mimeType - mime type to use.
* If auto (default), then it will be picked based on the render target type.
* @param textureIndex - index of the texture to use in the render target (only in case of multiple render target)
*/
exportRenderTarget(target, mimeType = 'auto', textureIndex = 0) {
const hdrFormats = ['image/x-exr'];
const texture = Array.isArray(target.texture) ? target.texture[textureIndex] : target.texture;
let hdr = texture.type === HalfFloatType || texture.type === FloatType;
if (mimeType === 'auto') {
mimeType = hdr ? 'image/x-exr' : 'image/png';
}
if (!hdrFormats.includes(mimeType))
hdr = false;
let buffer;
if (!hdr) {
const url = this.renderTargetToDataUrl(target, mimeType === 'auto' ? undefined : mimeType, 90, textureIndex);
buffer = base64ToArrayBuffer(url.split(',')[1]);
mimeType = url.split(';')[0].split(':')[1];
}
else {
if (mimeType !== 'image/x-exr') {
console.warn('RenderManager: mimeType ', mimeType, ' is not supported for HDR. Using EXR instead');
mimeType = 'image/x-exr';
}
const exporter = new EXRExporter2();
buffer = exporter.parse(this._renderer, target, { textureIndex }).buffer;
}
const b = new Blob([buffer], { type: mimeType });
b.ext = mimeType === 'image/x-exr' ? 'exr' : mimeType.split('/')[1];
return b;
}
// endregion
// region Events Dispatch
_updated(data) {
this.dispatchEvent({ ...data, type: 'update' });
}
// endregion
_createTargetClass(clazz, size, options) {
const processNewTarget = this._processNewTarget;
const disposeTarget = this.disposeTarget.bind(this);
return new class RenderTarget extends clazz {
constructor(renderManager, ...ps) {
super(...ps);
this.renderManager = renderManager;
this.assetType = 'renderTarget';
this.name = 'RenderTarget';
// required for uiconfig.js. see UiConfigMethods.getValue
// eslint-disable-next-line @typescript-eslint/naming-convention
this._ui_isPrimitive = true;
this.uuid = generateUUID();
const ops = ps[ps.length - 1];
const colorSpace = ops?.colorSpace;
this._initTexture(colorSpace);
}
_initTexture(colorSpace) {
if (Array.isArray(this.texture)) {
this.texture.forEach(t => {
if (colorSpace !== undefined)
t.colorSpace = colorSpace;
t._target = this;
t.toJSON = () => {
console.warn('Multiple render target texture.toJSON not supported yet.');
return {};
};
});
}
else {
this.texture._target = this;
// if (colorSpace !== undefined) this.texture.colorSpace = colorSpace
this.texture.toJSON = () => ({
isRenderTargetTexture: true,
}); // so that it doesn't get serialized
}
}
setSize(w, h, depth) {
super.setSize(Math.floor(w), Math.floor(h), depth);
// console.log('setSize', w, h, depth)
return this;
}
clone(trackTarget = true) {
if (this.isTemporary)
throw 'Cloning temporary render targets not supported'; // todo why?
if (Array.isArray(this.texture))
throw 'Cloning multiple render targets not supported';
// Note: todo: webgl render target.clone messes up the texture, by not copying isRenderTargetTexture prop and maybe some other stuff. So its better to just create a new one
// const cloned = super.clone() as IRenderTarget
const cloned = new this.constructor(this.renderManager);
cloned.copy(this);
cloned._initTexture((Array.isArray(this.texture) ? this.texture[0] : this.texture)?.colorSpace);
const tex = cloned.texture;
if (Array.isArray(tex))
tex.forEach(t => t.isRenderTargetTexture = true);
else
tex.isRenderTargetTexture = true;
return processNewTarget(cloned, this.sizeMultiplier || 1, trackTarget);
}
// copy(source: IRenderTarget|RenderTarget): this {
// super.copy(source as any)
// return this
// }
// Note - by default unregister need to be false.
dispose(unregister = false) {
if (unregister === true)
disposeTarget(this, true);
else
super.dispose();
}
}(this, ...size, options);
}
/**
* @deprecated use renderScale instead
*/
get displayCanvasScaling() {
console.error('displayCanvasScaling is deprecated, use renderScale instead');
return this.renderScale;
}
/**
* @deprecated use renderScale instead
*/
set displayCanvasScaling(value) {
console.error('displayCanvasScaling is deprecated, use renderScale instead');
this.renderScale = value;
}
};
RenderManager.POWER_PREFERENCE = 'high-performance';
__decorate([
uiMonitor('Render Size')
], RenderManager.prototype, "_renderSize", void 0);
__decorate([
uiSlider('Render Scale', [0.1, 8], 0.05) // keep here in code so its at the top in the UI
], RenderManager.prototype, "renderScale", null);
__decorate([
serialize(),
uiDropdown('Shadow Map Type', ['BasicShadowMap', 'PCFShadowMap', 'PCFSoftShadowMap', 'VSMShadowMap'].map((v, i) => ({ label: v, value: i })), { tags: ['advanced'] }),
bindToValue({ obj: 'shadowMap', key: 'type', onChange: RenderManager.prototype._shadowMapTypeChanged })
], RenderManager.prototype, "shadowMapType", void 0);
__decorate([
bindToValue({ obj: 'renderer', key: 'shadowMap' })
], RenderManager.prototype, "shadowMap", void 0);
__decorate([
uiConfig(undefined, { label: 'Passes', tags: ['advanced'], order: 1000 })
], RenderManager.prototype, "_passes", void 0);
__decorate([
uiToggle(),
serialize()
], RenderManager.prototype, "stableNoise", void 0);
__decorate([
onChange2(RenderManager.prototype.rebuildPipeline)
], RenderManager.prototype, "autoBuildPipeline", void 0);
__decorate([
uiButton('Rebuild Pipeline', { sendArgs: false, tags: ['advanced'] })
], RenderManager.prototype, "rebuildPipeline", null);
__decorate([
serialize()
], RenderManager.prototype, "useLegacyLights", null);
RenderManager = RenderManager_1 = __decorate([
serializable('RenderManager'),
uiFolderContainer('Render Manager')
], RenderManager);
export { RenderManager };
//# sourceMappingURL=RenderManager.js.map