playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
212 lines (211 loc) • 6.34 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, FramePassCameraFrame } from "./frame-pass-camera-frame.js";
class CameraFrame {
_enabled = true;
rendering = {
renderFormats: [PIXELFORMAT_111110F, PIXELFORMAT_RGBA16F, PIXELFORMAT_RGBA32F],
stencil: false,
renderTargetScale: 1,
samples: 1,
sceneColorMap: false,
sceneDepthMap: false,
toneMapping: 0,
sharpness: 0
};
ssao = {
type: SSAOTYPE_NONE,
blurEnabled: true,
randomize: false,
intensity: 0.5,
radius: 30,
samples: 12,
power: 6,
minAngle: 10,
scale: 1
};
bloom = {
intensity: 0,
blurLevel: 16
};
grading = {
enabled: false,
brightness: 1,
contrast: 1,
saturation: 1,
tint: new Color(1, 1, 1, 1)
};
colorLUT = {
texture: null,
intensity: 1,
texture2: null,
intensity2: 1,
blend: 0
};
vignette = {
intensity: 0,
inner: 0.5,
outer: 1,
curvature: 0.5,
color: new Color(0, 0, 0)
};
taa = {
enabled: false,
jitter: 1
};
fringing = {
intensity: 0
};
colorEnhance = {
enabled: false,
shadows: 0,
highlights: 0,
vibrance: 0,
midtones: 0,
dehaze: 0
};
dof = {
enabled: false,
nearBlur: false,
focusDistance: 100,
focusRange: 10,
blurRadius: 3,
blurRings: 4,
blurRingPoints: 5,
highQuality: true
};
debug = null;
options = new CameraFrameOptions();
renderPassCamera = null;
constructor(app, cameraComponent) {
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.framePasses = [this.renderPassCamera];
}
disable() {
const cameraComponent = this.cameraComponent;
cameraComponent.framePasses?.forEach((renderPass) => {
renderPass.destroy();
});
cameraComponent.framePasses = [];
cameraComponent.rendering = null;
cameraComponent.jitter = 0;
cameraComponent.shaderParams.ssaoEnabled = false;
this.renderPassCamera = null;
}
createRenderPass() {
return new FramePassCameraFrame(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, colorEnhance, 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.colorLUT2 = this.colorLUT.texture2;
composePass.colorLUT2Intensity = this.colorLUT.intensity2;
composePass.colorLUTBlend = this.colorLUT.blend;
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.vignetteColor.copy(vignette.color);
}
composePass.fringingEnabled = fringing.intensity > 0;
if (composePass.fringingEnabled) {
composePass.fringingIntensity = fringing.intensity;
}
composePass.colorEnhanceEnabled = colorEnhance.enabled;
if (colorEnhance.enabled) {
composePass.colorEnhanceShadows = colorEnhance.shadows;
composePass.colorEnhanceHighlights = colorEnhance.highlights;
composePass.colorEnhanceVibrance = colorEnhance.vibrance;
composePass.colorEnhanceMidtones = colorEnhance.midtones;
composePass.colorEnhanceDehaze = colorEnhance.dehaze;
}
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
};