playcanvas
Version:
PlayCanvas WebGL game engine
194 lines (191 loc) • 6.12 kB
JavaScript
import { Color } from '../../core/math/color.js';
import { math } from '../../core/math/math.js';
import { PIXELFORMAT_111110F, PIXELFORMAT_RGBA16F, PIXELFORMAT_RGBA32F } from '../../platform/graphics/constants.js';
import { SSAOTYPE_NONE } from './constants.js';
import { CameraFrameOptions, RenderPassCameraFrame } from './render-pass-camera-frame.js';
class CameraFrame {
constructor(app, cameraComponent){
this._enabled = true;
this.rendering = {
renderFormats: [
PIXELFORMAT_111110F,
PIXELFORMAT_RGBA16F,
PIXELFORMAT_RGBA32F
],
stencil: false,
renderTargetScale: 1.0,
samples: 1,
sceneColorMap: false,
sceneDepthMap: false,
toneMapping: 0,
sharpness: 0.0
};
this.ssao = {
type: SSAOTYPE_NONE,
blurEnabled: true,
randomize: false,
intensity: 0.5,
radius: 30,
samples: 12,
power: 6,
minAngle: 10,
scale: 1
};
this.bloom = {
intensity: 0,
blurLevel: 16
};
this.grading = {
enabled: false,
brightness: 1,
contrast: 1,
saturation: 1,
tint: new Color(1, 1, 1, 1)
};
this.colorLUT = {
texture: null,
intensity: 1
};
this.vignette = {
intensity: 0,
inner: 0.5,
outer: 1,
curvature: 0.5
};
this.taa = {
enabled: false,
jitter: 1
};
this.fringing = {
intensity: 0
};
this.dof = {
enabled: false,
nearBlur: false,
focusDistance: 100,
focusRange: 10,
blurRadius: 3,
blurRings: 4,
blurRingPoints: 5,
highQuality: true
};
this.debug = null;
this.options = new CameraFrameOptions();
this.renderPassCamera = null;
this.app = app;
this.cameraComponent = cameraComponent;
this.updateOptions();
this.enable();
this.cameraLayersChanged = cameraComponent.on('set:layers', ()=>{
if (this.renderPassCamera) this.renderPassCamera.layersDirty = true;
});
}
destroy() {
this.disable();
this.cameraLayersChanged.off();
}
enable() {
this.renderPassCamera = this.createRenderPass();
this.cameraComponent.renderPasses = [
this.renderPassCamera
];
}
disable() {
const cameraComponent = this.cameraComponent;
cameraComponent.renderPasses?.forEach((renderPass)=>{
renderPass.destroy();
});
cameraComponent.renderPasses = [];
cameraComponent.rendering = null;
cameraComponent.jitter = 0;
cameraComponent.shaderParams.ssaoEnabled = false;
this.renderPassCamera = null;
}
createRenderPass() {
return new RenderPassCameraFrame(this.app, this, this.cameraComponent, this.options);
}
set enabled(value) {
if (this._enabled !== value) {
if (value) {
this.enable();
} else {
this.disable();
}
this._enabled = value;
}
}
get enabled() {
return this._enabled;
}
updateOptions() {
const { options, rendering, bloom, taa, ssao } = this;
options.stencil = rendering.stencil;
options.samples = rendering.samples;
options.sceneColorMap = rendering.sceneColorMap;
options.prepassEnabled = rendering.sceneDepthMap;
options.bloomEnabled = bloom.intensity > 0;
options.taaEnabled = taa.enabled;
options.ssaoType = ssao.type;
options.ssaoBlurEnabled = ssao.blurEnabled;
options.formats = rendering.renderFormats.slice();
options.dofEnabled = this.dof.enabled;
options.dofNearBlur = this.dof.nearBlur;
options.dofHighQuality = this.dof.highQuality;
}
update() {
if (!this._enabled) return;
const cameraComponent = this.cameraComponent;
const { options, renderPassCamera, rendering, bloom, grading, vignette, fringing, taa, ssao } = this;
this.updateOptions();
renderPassCamera.update(options);
const { composePass, bloomPass, ssaoPass, dofPass } = renderPassCamera;
renderPassCamera.renderTargetScale = math.clamp(rendering.renderTargetScale, 0.1, 1);
composePass.toneMapping = rendering.toneMapping;
composePass.sharpness = rendering.sharpness;
if (options.bloomEnabled && bloomPass) {
composePass.bloomIntensity = bloom.intensity;
bloomPass.blurLevel = bloom.blurLevel;
}
if (options.dofEnabled) {
dofPass.focusDistance = this.dof.focusDistance;
dofPass.focusRange = this.dof.focusRange;
dofPass.blurRadius = this.dof.blurRadius;
dofPass.blurRings = this.dof.blurRings;
dofPass.blurRingPoints = this.dof.blurRingPoints;
}
if (options.ssaoType !== SSAOTYPE_NONE) {
ssaoPass.intensity = ssao.intensity;
ssaoPass.power = ssao.power;
ssaoPass.radius = ssao.radius;
ssaoPass.sampleCount = ssao.samples;
ssaoPass.minAngle = ssao.minAngle;
ssaoPass.scale = ssao.scale;
ssaoPass.randomize = ssao.randomize;
}
composePass.gradingEnabled = grading.enabled;
if (grading.enabled) {
composePass.gradingSaturation = grading.saturation;
composePass.gradingBrightness = grading.brightness;
composePass.gradingContrast = grading.contrast;
composePass.gradingTint = grading.tint;
}
composePass.colorLUT = this.colorLUT.texture;
composePass.colorLUTIntensity = this.colorLUT.intensity;
composePass.vignetteEnabled = vignette.intensity > 0;
if (composePass.vignetteEnabled) {
composePass.vignetteInner = vignette.inner;
composePass.vignetteOuter = vignette.outer;
composePass.vignetteCurvature = vignette.curvature;
composePass.vignetteIntensity = vignette.intensity;
}
composePass.fringingEnabled = fringing.intensity > 0;
if (composePass.fringingEnabled) {
composePass.fringingIntensity = fringing.intensity;
}
cameraComponent.jitter = taa.enabled ? taa.jitter : 0;
composePass.debug = this.debug;
if (composePass.debug === 'ssao' && options.ssaoType === SSAOTYPE_NONE) composePass.debug = null;
if (composePass.debug === 'vignette' && !composePass.vignetteEnabled) composePass.debug = null;
}
}
export { CameraFrame };