@needle-tools/engine
Version:
Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.
104 lines (82 loc) • 3.47 kB
text/typescript
import type { DepthOfFieldEffect } from "postprocessing";
import { Mathf } from "../../../engine/engine_math.js";
import { MODULES } from "../../../engine/engine_modules.js";
import { serializable } from "../../../engine/engine_serialization.js";
import { getParam, isMobileDevice } from "../../../engine/engine_utils.js";
import { PostProcessingEffect } from "../PostProcessingEffect.js";
import { VolumeParameter } from "../VolumeParameter.js";
import { registerCustomEffectType } from "../VolumeProfile.js";
export enum DepthOfFieldMode {
Off = 0,
Gaussian = 1,
Bokeh = 2,
}
const debug = getParam("debugpost");
/**
* @category Effects
* @group Components
*/
export class DepthOfField extends PostProcessingEffect {
get typeName() {
return "DepthOfField";
}
()
mode!: DepthOfFieldMode;
(VolumeParameter)
readonly focusDistance: VolumeParameter = new VolumeParameter(1);
(VolumeParameter)
readonly focalLength: VolumeParameter = new VolumeParameter(.2);
(VolumeParameter)
readonly aperture: VolumeParameter = new VolumeParameter(20);
(VolumeParameter)
readonly gaussianMaxRadius: VolumeParameter = new VolumeParameter();
(VolumeParameter)
readonly resolutionScale: VolumeParameter = new VolumeParameter(1 * 1 / window.devicePixelRatio);
(VolumeParameter)
readonly bokehScale: VolumeParameter = new VolumeParameter();
init() {
this.focalLength.valueProcessor = v => {
const t = v / 300;
const max = 2;// this.context.mainCameraComponent?.farClipPlane ?? 10;
return Mathf.lerp(max, .01, t);
};
const maxBokehScale = 20;
this.aperture.valueProcessor = v => {
const t = 1 - v / 32;
return Mathf.lerp(1, maxBokehScale, t);
};
}
onCreateEffect() {
if (this.mode === DepthOfFieldMode.Off) {
if (debug) console.warn("DepthOfField: Mode is set to Off");
return undefined;
}
// const factor = 1 / window.devicePixelRatio;
// if (this.resolutionScale === undefined) {
// let defaultValue = 1;
// if(isMobileDevice()) defaultValue = .6;
// this.resolutionScale = new VolumeParameter(defaultValue * factor);
// }
// console.log(this.focusDistance.overrideState, this.focusDistance.value);
// const depth = new DepthEffect({
// inverted: true,
// // blendFunction: BlendFunction.SET,
// });
const dof = new MODULES.POSTPROCESSING.MODULE.DepthOfFieldEffect(this.context.mainCamera!, {
worldFocusRange: .2,
focalLength: 1,
bokehScale: 20,
resolutionScale: this.resolutionScale.value,
});
this.focusDistance.onValueChanged = v => {
dof.cocMaterial.worldFocusDistance = v;
}
this.focalLength.onValueChanged = v => dof.cocMaterial.worldFocusRange = v;
this.aperture.onValueChanged = v => dof.bokehScale = v;
if (this.resolutionScale) this.resolutionScale.onValueChanged = v => dof.resolution.scale = v;
return [dof];
}
unapply() {
}
}
registerCustomEffectType("DepthOfField", DepthOfField);