@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
136 lines (128 loc) • 4.35 kB
text/typescript
import {Constructor} from '../../../../../types/GlobalTypes';
import {BaseNodeType} from '../../../_Base';
import {ParamConfig} from '../../../utils/params/ParamsConfig';
import {NodeContext} from '../../../../poly/NodeContext';
import {RootManagerNode} from '../../Root';
// import {ColorConversion} from '../../../../../core/Color';
import {Color} from 'three';
import {TypeAssert} from '../../../../poly/Assert';
export enum BackgroundMode {
NONE = 'none',
COLOR = 'color',
TEXTURE = 'texture',
}
export const BACKGROUND_MODES: BackgroundMode[] = [BackgroundMode.NONE, BackgroundMode.COLOR, BackgroundMode.TEXTURE];
const CallbackOptions = {
cook: false,
callback: (node: BaseNodeType) => {
SceneBackgroundController.update(node as RootManagerNode);
},
};
export function SceneBackgroundParamConfig<TBase extends Constructor>(Base: TBase) {
return class Mixin extends Base {
// background
/** @param set background mode (none, color or texture). Note that in order to have a transparent background, you also need to set the renderer's alpha to true. In order to do so, you may need to create a rop/WebGLRenderer node, set it alpha parameter, and assign the node to your camera. */
backgroundMode = ParamConfig.INTEGER(BACKGROUND_MODES.indexOf(BackgroundMode.COLOR), {
menu: {
entries: BACKGROUND_MODES.map((mode, i) => {
return {name: mode, value: i};
}),
},
...CallbackOptions,
separatorBefore: true,
});
/** @param background color */
bgColor = ParamConfig.COLOR([0.01, 0.01, 0.01], {
visibleIf: {backgroundMode: BACKGROUND_MODES.indexOf(BackgroundMode.COLOR)},
...CallbackOptions,
// conversion: ColorConversion.SRGB_TO_LINEAR,
});
/** @param background texture */
bgTexture = ParamConfig.NODE_PATH('', {
visibleIf: {backgroundMode: BACKGROUND_MODES.indexOf(BackgroundMode.TEXTURE)},
nodeSelection: {
context: NodeContext.COP,
},
// dependentOnFoundNode: false,
...CallbackOptions,
});
/** @param background blur */
bgBlur = ParamConfig.FLOAT(0, {
visibleIf: {backgroundMode: BACKGROUND_MODES.indexOf(BackgroundMode.TEXTURE)},
range: [0, 1],
rangeLocked: [true, false],
...CallbackOptions,
});
/** @param background intensity */
bgIntensity = ParamConfig.FLOAT(1, {
visibleIf: {backgroundMode: BACKGROUND_MODES.indexOf(BackgroundMode.TEXTURE)},
range: [0, 2],
rangeLocked: [true, false],
...CallbackOptions,
});
};
}
const CALLBACK_NAME = 'SceneBackgroundController';
export class SceneBackgroundController {
constructor(protected node: RootManagerNode) {}
addHooks() {
const p = this.node.p;
const params = [p.backgroundMode, p.bgColor, p.bgTexture];
for (const param of params) {
param.addPostDirtyHook(CALLBACK_NAME, this._updateBound);
}
}
setMode(mode: BackgroundMode) {
this.node.p.backgroundMode.set(BACKGROUND_MODES.indexOf(mode));
}
backgroundMode(): BackgroundMode {
return BACKGROUND_MODES[this.node.pv.backgroundMode];
}
private _updateBound = this.update.bind(this);
async update() {
const backgroundMode = this.backgroundMode();
switch (backgroundMode) {
case BackgroundMode.NONE: {
return this._setBackgroundNone();
}
case BackgroundMode.COLOR: {
return await this._setBackgroundColor();
}
case BackgroundMode.TEXTURE: {
return await this._setBackgroundTexture();
}
}
TypeAssert.unreachable(backgroundMode);
}
private _setBackgroundNone() {
const scene = this.node.object;
scene.background = null;
}
private async _setBackgroundColor() {
const scene = this.node.object;
const pv = this.node.pv;
await this.node.p.bgColor.compute();
if (scene.background && scene.background instanceof Color) {
scene.background.copy(pv.bgColor);
} else {
scene.background = pv.bgColor;
}
}
private async _setBackgroundTexture() {
const scene = this.node.object;
const pv = this.node.pv;
const node = pv.bgTexture.nodeWithContext(NodeContext.COP);
if (node) {
const container = await node.compute();
scene.background = container.texture();
} else {
this.node.states.error.set('bgTexture node not found');
scene.background = null;
}
scene.backgroundBlurriness = pv.bgBlur;
scene.backgroundIntensity = pv.bgIntensity;
}
static update(node: RootManagerNode) {
node.sceneBackgroundController.update();
}
}