import { ObjectProxy } from '@uino/base-thing';
import { Utils } from '../common/Utils';
import { BaseComponent } from './BaseComponent';
const __ = {
private: Symbol('private'),
}
/**
* @class CameraPostEffectComponent
* 屏幕级后期
* @memberof THING
* @extends THING.BaseComponent
* @public
*/
class CameraPostEffectComponent extends BaseComponent {
/**
* 相机的渲染效果,可以在这里更改一些屏幕后期效果。
*/
constructor() {
super();
this[__.private] = {};
let _private = this[__.private];
_private.needsRefresh = false;
/**
* Temporal super sampling
* @typedef {object} TemporalSuperSampling
* @property {boolean} enable True indicates enable it.
* @property {number} size The max frames.
*/
_private.temporalSuperSampling = {
enable: false,
size: 30
};
/**
* 辉光效果
* @typedef {object} Bloom
* @property {boolean} enable 是否开启
* @property {number} strength 强度
* @property {number} radius 半径
* @property {number} threshold 阈值
* @public
*/
_private.bloom = {
enable: false,
strength: 0.14,
radius: 0.4,
threshold: 0.7
};
/**
* 屏幕空间环境光遮蔽配置
* @remarks 工作空间中的采样半径。<br>
* 较大的半径会产生更柔和的阴影。<br>
* 但是需要更高的质量,否则会有更明显的伪影
* @typedef {object} ScreenSpaceAmbientOcclusion
* @property {boolean} enable 是否开启
* @property {number} radius 半径
* @property {string} quality SSAO的质量。可选值为'low'|'medium'|'high'|'ultra'。
* @property {number} intensity 强度
* @property {boolean} temporalFilter 是否在时序超采样模式下使用滤波器。
* @property {boolean} ignoreTransparent 是否忽略透明物体。
* @public
*/
_private.screenSpaceAmbientOcclusion = {
enable: false,
radius: 0.2,
quality: 'medium',
intensity: 0.8,
temporalFilter: true,
ignoreTransparent: false
};
/**
* GTAO
* @typedef {object} GroundTruthAmbientOcclusion
* @property {boolean} enable 是否开启
* @property {boolean} multiBounce是否开启多次反弹 开启产生更加真实和逼真的环境光遮蔽效果,也会增加计算的复杂度和资源消耗
* @property {number} maxDistance 环境光遮蔽计算的最大距离
* @property {number} maxPixel 环境光遮蔽计算的最大像素数量
* @property {number} rayMarchSegment 光线追踪的段数
* @property {number} darkFactor 深度因子
* @public
*/
_private.groundTruthAmbientOcclusion = {
enable: false,
multiBounce: false,
maxDistance: 10,
maxPixel: 14,
rayMarchSegment: 10,
darkFactor: 1.
}
/**
* 屏幕空间反射配置
* @typedef {object} ScreenSpaceReflection
* @property {boolean} enable 开关
* @property {number} maxRayDistance 反射光线追踪的最大距离
* @property {number} pixelStride 步长
* @property {boolean} enablePixelStrideZCutoff 是否限制反射光线的最大距离,以避免对远处或过远的物体进行反射计算
* @property {number} falloff 屏幕空间反射效果的衰减函数或者衰减参数
* @property {number} strength 反射强度
* @property {number} pixelStrideZCutoff 屏幕空间反射计算中根据像素之间的距离进行截断
* @property {number} screenEdgeFadeStart 屏幕边缘开始淡化的距离
* @property {number} eyeFadeStart 屏幕空间反射效果在摄像机视角附近开始逐渐减弱的位置
* @property {number} eyeFadeEnd 屏幕空间反射效果在摄像机视角附近结束减弱的位置
* @property {number} minGlossiness 控制屏幕空间反射效果中反射光滑度的最小值,具有高光滑度的表面通常会产生清晰的反射,而具有低光滑度的表面则会产生模糊的反射。
* @public
*/
_private.screenSpaceReflection = {
enable: false,
maxRayDistance: 200,
pixelStride: 16,
enablePixelStrideZCutoff: false,
falloff: 0,
strength: 0.8,
pixelStrideZCutoff: 50,
screenEdgeFadeStart: 0.9,
eyeFadeStart: 0.4,
eyeFadeEnd: 0.8,
minGlossiness: 0.2
};
/**
* 颜色校正配置
* @typedef {object} ColorCorrection
* @property {boolean} enable 是否开启
* @property {number} exposure 曝光度
* @property {number} brightness 亮度
* @property {number} contrast 对比度
* @property {number} saturation 饱和度
* @property {number} gamma 伽马值
* @public
*/
_private.colorCorrection = {
enable: true,
exposure: 0,
brightness: 0,
contrast: 1.1,
saturation: 1.1,
gamma: 1
};
/**
* 景深效果配置
* @typedef {object} Dof
* @property {boolean} enable 是否开启
* @property {number} focalDepth 相机焦点的深度位置
* @property {number} focalLength 焦距
* @property {number} fstop 光圈
* @property {number} maxblur 最大允许的模糊半径
* @property {number} threshold 阈值
* @property {number} gain 模糊效果的增益因子 越大越模糊
* @property {number} bias 偏差 可以改变焦点周围模糊区域的过渡方式
* @property {number} dithering 抖动 改善模糊边缘的过渡效果
* @public
*/
_private.dof = {
enable: false,
focalDepth: 1,
focalLength: 24,
fstop: 0.9,
maxblur: 1.0,
threshold: 0.9,
gain: 1.0,
bias: 0.5,
dithering: 0.0001
};
/**
* 镜头暗角效果配置
* @typedef {object} Vignetting
* @property {boolean} enable 是否开启
* @property {number[]} color 边缘的颜色,仅适用于颜色类型
* @property {number} offset 偏移
* @public
*/
_private.vignetting = {
enable: false,
color: [0, 0, 0],
offset: 1.5
};
/**
* 模糊边缘效果配置
* @typedef {object} BlurEdge
* @property {boolean} enable 是否开启
* @property {number} offset 偏移
* @public
*/
_private.blurEdge = {
enable: false,
offset: 1.0
};
/**
* 电影效果配置
* @typedef {object} Film
* @property {boolean} enable 是否开启
* @property {boolean} grayscale 是否开启灰度模式(黑白效果)
* @property {number} noiseIntensity 噪声强度
* @property {number} scanlinesIntensity 扫描线强度
* @property {number} scanlinesCount 扫面线个数
* @public
*/
_private.film = {
enable: false,
grayscale: false,
noiseIntensity: 0.35,
scanlinesIntensity: 0,
scanlinesCount: 2048
};
/**
* 色差
* @typedef {object} ChromaticAberration
* @property {boolean} enable 是否开启
* @property {number} chromaFactor 色彩分离系数
* @public
*/
_private.chromaticAberration = {
enable: false,
chromaFactor: 0.025
};
/**
* FXAA的配置信息。
* @typedef {object} FXAA
* @property {boolean} enable 是否开启。True表示开启。
* @public
*/
_private.FXAA = {
enable: false
};
/**
* MSAA配置信息。
* @typedef {object} MSAA
* @property {boolean} enable 是否开启。True表示开启。
* @public
*/
_private.MSAA = {
enable: true
};
_private.onChange = null;
_private.objectProxy = new ObjectProxy({
data: {
enable: true,
bloom: _private.bloom,
screenSpaceAmbientOcclusion: _private.screenSpaceAmbientOcclusion,
groundTruthAmbientOcclusion: _private.groundTruthAmbientOcclusion,
screenSpaceReflection: _private.screenSpaceReflection,
colorCorrection: _private.colorCorrection,
dof: _private.dof,
vignetting: _private.vignetting,
blurEdge: _private.blurEdge,
film: _private.film,
chromaticAberration: _private.chromaticAberration,
FXAA: _private.FXAA,
MSAA: _private.MSAA,
temporalSuperSampling: _private.temporalSuperSampling,
},
onConvertValue: function (type, value) {
if (type == 'color') {
return Utils.parseColor(value, [1, 1, 1]);
}
},
onChange: function (ev) {
_private.needsRefresh = true;
if (_private.onChange) {
_private.onChange(ev);
}
}
});
// Refresh effect by current config
this._refresh();
// Show config always
Object.defineProperty(this, 'customFormatters', {
enumerable: false,
configurable: false,
get: function () {
return ['object', { object: _private.objectProxy.dataProxy }];
}
});
}
// #region Private Functions
_refresh() {
let object = this.object;
if (!object) {
return;
}
let _private = this[__.private];
if (!_private.needsRefresh) {
return;
}
_private.needsRefresh = false;
object.node.setPostEffect({
temporalSuperSampling: _private.temporalSuperSampling,
postEffect: {
enable: _private.objectProxy.dataProxy.enable,
bloom: _private.bloom,
screenSpaceAmbientOcclusion: _private.screenSpaceAmbientOcclusion,
groundTruthAmbientOcclusion: _private.groundTruthAmbientOcclusion,
screenSpaceReflection: _private.screenSpaceReflection,
colorCorrection: _private.colorCorrection,
dof: _private.dof,
vignetting: _private.vignetting,
blurEdge: _private.blurEdge,
film: _private.film,
chromaticAberration: _private.chromaticAberration,
FXAA: _private.FXAA,
MSAA: _private.MSAA,
}
});
}
// #endregion
// #region BaseComponent Overrides
onAdd(object) {
super.onAdd(object);
// Refresh config before render if needed
this.app.addBeforeRenderCallback(this._onBeforeRenderCallback = () => {
this._refresh();
});
}
onRemove() {
let _private = this[__.private];
_private.objectProxy.dispose();
this.app.removeBeforeRenderCallback(this._onBeforeRenderCallback);
super.onRemove();
}
onCopy(component) {
this.config = component.config;
}
// #endregion
/**
* 是否开启
* @type {boolean}
* @example
* let app = THING.App.current
* app.camera.postEffect.enable = false;
* // @expect(app.camera.postEffect.enable == false)
* @public
*/
get enable() {
let _private = this[__.private];
return _private.objectProxy.dataProxy.enable;
}
set enable(value) {
let _private = this[__.private];
if (_private.objectProxy.dataProxy.enable == value) {
return;
}
_private.objectProxy.dataProxy.enable = value;
this._refresh();
}
/**
* TSS效果 在连续的帧之间进行抖动来减少图像中的锯齿
* @type {TemporalSuperSampling}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.temporalSuperSampling.enable = true;
* // @expect(app.camera.postEffect.temporalSuperSampling.enable == true)
* @public
*/
get temporalSuperSampling() {
return this[__.private].objectProxy.dataProxy.temporalSuperSampling;
}
set temporalSuperSampling(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.temporalSuperSampling, value, true);
}
/**
* 屏幕级辉光效果
* @type {Bloom}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.bloom.enable = true;
* // @expect(app.camera.postEffect.bloom.enable == true)
* @public
*/
get bloom() {
return this[__.private].objectProxy.dataProxy.bloom;
}
set bloom(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.bloom, value, true);
}
/**
* 屏幕空间环境光遮蔽(SSAO)
* @type {ScreenSpaceAmbientOcclusion}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.screenSpaceAmbientOcclusion.enable = true;
* // @expect(app.camera.postEffect.screenSpaceAmbientOcclusion.enable == true)
* @public
*/
get screenSpaceAmbientOcclusion() {
return this[__.private].objectProxy.dataProxy.screenSpaceAmbientOcclusion;
}
set screenSpaceAmbientOcclusion(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.screenSpaceAmbientOcclusion, value, true);
}
/**
* 真实世界环境光遮蔽(GTAO)
* @type {GroundTruthAmbientOcclusion}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.groundTruthAmbientOcclusion.enable = true;
* // @expect(app.camera.postEffect.groundTruthAmbientOcclusion.enable == true)
* @public
*/
get groundTruthAmbientOcclusion() {
return this[__.private].objectProxy.dataProxy.groundTruthAmbientOcclusion;
}
set groundTruthAmbientOcclusion(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.groundTruthAmbientOcclusion, value, true);
}
/**
* 屏幕空间反射(SSR) 模拟出物体表面的反射效果,从而增强场景的真实感和逼真度
* @type {ScreenSpaceReflection}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.screenSpaceReflection.enable = true;
* // @expect(app.camera.postEffect.screenSpaceReflection.enable == true)
* @public
*/
get screenSpaceReflection() {
return this[__.private].objectProxy.dataProxy.screenSpaceReflection;
}
set screenSpaceReflection(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.screenSpaceReflection, value, true);
}
/**
* 颜色校正
* @type {ColorCorrection}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.colorCorrection.enable = true;
* // @expect(app.camera.postEffect.colorCorrection.enable == true)
* @public
*/
get colorCorrection() {
return this[__.private].objectProxy.dataProxy.colorCorrection;
}
set colorCorrection(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.colorCorrection, value, true);
}
/**
* 景深效果
* @type {Dof}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.dof.enable = true;
* // @expect(app.camera.postEffect.dof.enable == true)
* @public
*/
get dof() {
return this[__.private].objectProxy.dataProxy.dof;
}
set dof(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.dof, value, true);
}
/**
* 暗角效果 屏幕边缘给定一个颜色进行填充,并在中心位置过渡到场景
* @type {Vignetting}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.vignetting.enable = true;
* // @expect(app.camera.postEffect.vignetting.enable == true)
* @public
*/
get vignetting() {
return this[__.private].objectProxy.dataProxy.vignetting;
}
set vignetting(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.vignetting, value, true);
}
/**
* 边缘模糊
* @type {BlurEdge}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.blurEdge.enable = true;
* // @expect(app.camera.postEffect.blurEdge.enable == true)
* @public
*/
get blurEdge() {
return this[__.private].objectProxy.dataProxy.blurEdge;
}
set blurEdge(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.blurEdge, value, true);
}
/**
* 胶片效果
* @type {Film}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.film.enable = true;
* // @expect(app.camera.postEffect.film.enable == true)
* @public
*/
get film() {
return this[__.private].objectProxy.dataProxy.film;
}
set film(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.film, value, true);
}
/**
* 色彩分离效果
* @type {ChromaticAberration}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.chromaticAberration.enable = true;
* // @expect(app.camera.postEffect.chromaticAberration.enable == true)
* @public
*/
get chromaticAberration() {
return this[__.private].objectProxy.dataProxy.chromaticAberration;
}
set chromaticAberration(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.chromaticAberration, value, true);
}
/**
* 快速近似抗锯齿
* @type {FXAA}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.FXAA.enable = true;
* // @expect(app.camera.postEffect.FXAA.enable == true)
* @public
*/
get FXAA() {
return this[__.private].objectProxy.dataProxy.FXAA;
}
set FXAA(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.FXAA, value, true);
}
/**
* 多重采样抗锯齿
* @type {MSAA}
* @example
* let app = THING.App.current
* app.camera.postEffect.config.MSAA.enable = false;
* // @expect(app.camera.postEffect.MSAA.enable == false)
* @public
*/
get MSAA() {
return this[__.private].objectProxy.dataProxy.MSAA;
}
set MSAA(value) {
let _private = this[__.private];
Utils.mergeObject(_private.objectProxy.dataProxy.MSAA, value, true);
}
/**
* 后期效果的配置。
* @typedef {object} PostEffectInfo
* @property {boolean} enable true表示开启。是否开启后期效果
* @property {Bloom} bloom 泛光效果。
* @property {ScreenSpaceAmbientOcclusion} screenSpaceAmbientOcclusion 屏幕空间环境光遮蔽(SSAO)效果。
* @property {GroundTruthAmbientOcclusion} groundTruthAmbientOcclusion 真实世界环境光遮蔽(GTAO)效果。
* @property {ScreenSpaceReflection} screenSpaceReflection 屏幕空间反射(SSR)效果。
* @property {ColorCorrection} colorCorrection 颜色校正效果。
* @property {Dof} dof 景深效果。
* @property {Vignetting} vignetting 暗角效果。
* @property {BlurEdge} blurEdge 边缘模糊效果。
* @property {Film} film 胶片效果。
* @property {ChromaticAberration} chromaticAberration 色彩分离效果。
* @property {FXAA} FXAA 快速近似抗锯齿效果。
* @property {MSAA} MSAA 多重采样抗锯齿效果。
* @property {TemporalSuperSampling} temporalSuperSampling 时序超采样效果。(TSS)
* @public
*/
/**
* 设置/获取 后期配置
* @type {PostEffectInfo}
* @example
* let app = THING.App.current
* app.camera.postEffect.config = {
* FXAA: {enable: true}
* };
* // @expect(app.camera.postEffect.config.FXAA.enable == true)
* @public
*/
get config() {
return this[__.private].objectProxy.dataProxy;
}
set config(value = {}) {
let _private = this[__.private];
let to = _private.objectProxy.dataProxy;
if (Utils.isValid(value.enable)) {
to.enable = value.enable;
}
Utils.mergeObject(to.bloom, value.bloom, true);
Utils.mergeObject(to.screenSpaceAmbientOcclusion, value.screenSpaceAmbientOcclusion, true);
Utils.mergeObject(to.groundTruthAmbientOcclusion, value.groundTruthAmbientOcclusion, true);
Utils.mergeObject(to.screenSpaceReflection, value.screenSpaceReflection, true);
Utils.mergeObject(to.colorCorrection, value.colorCorrection, true);
Utils.mergeObject(to.dof, value.dof, true);
Utils.mergeObject(to.vignetting, value.vignetting, true);
Utils.mergeObject(to.blurEdge, value.blurEdge, true);
Utils.mergeObject(to.film, value.film, true);
Utils.mergeObject(to.chromaticAberration, value.chromaticAberration, true);
Utils.mergeObject(to.FXAA, value.FXAA, true);
Utils.mergeObject(to.MSAA, value.MSAA, true);
Utils.mergeObject(to.temporalSuperSampling, value.temporalSuperSampling, true);
}
/**
* Get/Set when change callback function.
* @type {Function}
* @private
*/
get onChange() {
let _private = this[__.private];
return _private.onChange;
}
set onChange(value) {
let _private = this[__.private];
_private.onChange = value;
}
}
export { CameraPostEffectComponent }