UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

305 lines (304 loc) 9.37 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { Debug } from "../../core/debug.js"; 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 { /** * Creates a new CameraFrame instance. * * @param {AppBase} app - The application. * @param {CameraComponent} cameraComponent - The camera component. */ constructor(app, cameraComponent) { /** @private */ __publicField(this, "_enabled", true); /** * Rendering settings. * * @type {Rendering} */ __publicField(this, "rendering", { renderFormats: [PIXELFORMAT_111110F, PIXELFORMAT_RGBA16F, PIXELFORMAT_RGBA32F], stencil: false, renderTargetScale: 1, samples: 1, sceneColorMap: false, sceneDepthMap: false, toneMapping: 0, sharpness: 0 }); /** * SSAO settings. * * @type {Ssao} */ __publicField(this, "ssao", { type: SSAOTYPE_NONE, blurEnabled: true, randomize: false, intensity: 0.5, radius: 30, samples: 12, power: 6, minAngle: 10, scale: 1 }); /** * Bloom settings. * * @type {Bloom} */ __publicField(this, "bloom", { intensity: 0, blurLevel: 16 }); /** * Grading settings. * * @type {Grading} */ __publicField(this, "grading", { enabled: false, brightness: 1, contrast: 1, saturation: 1, tint: new Color(1, 1, 1, 1) }); /** * Color LUT settings. * * @type {ColorLUT} */ __publicField(this, "colorLUT", { texture: null, intensity: 1, texture2: null, intensity2: 1, blend: 0 }); /** * Vignette settings. * * @type {Vignette} */ __publicField(this, "vignette", { intensity: 0, inner: 0.5, outer: 1, curvature: 0.5, color: new Color(0, 0, 0) }); /** * Taa settings. * * @type {Taa} */ __publicField(this, "taa", { enabled: false, jitter: 1 }); /** * Fringing settings. * * @type {Fringing} */ __publicField(this, "fringing", { intensity: 0 }); /** * Color enhancement settings. * * @type {ColorEnhance} */ __publicField(this, "colorEnhance", { enabled: false, shadows: 0, highlights: 0, vibrance: 0, midtones: 0, dehaze: 0 }); /** * DoF settings. * * @type {Dof} */ __publicField(this, "dof", { enabled: false, nearBlur: false, focusDistance: 100, focusRange: 10, blurRadius: 3, blurRings: 4, blurRingPoints: 5, highQuality: true }); /** * Debug rendering. Set to null to disable. * * @type {null|'scene'|'ssao'|'bloom'|'vignette'|'dofcoc'|'dofblur'} */ __publicField(this, "debug", null); __publicField(this, "options", new CameraFrameOptions()); /** * @type {FramePassCameraFrame|null} * @private */ __publicField(this, "renderPassCamera", null); this.app = app; this.cameraComponent = cameraComponent; Debug.assert(cameraComponent, "CameraFrame: cameraComponent must be defined"); this.updateOptions(); this.enable(); this.cameraLayersChanged = cameraComponent.on("set:layers", () => { if (this.renderPassCamera) this.renderPassCamera.layersDirty = true; }); } /** * Destroys the camera frame, removing all render passes. */ 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; } /** * Creates a frame pass for the camera frame. Override this method to utilize a custom frame * pass, typically one that extends {@link FramePassCameraFrame}. * * @returns {FramePassCameraFrame} - The frame pass. */ createRenderPass() { return new FramePassCameraFrame(this.app, this, this.cameraComponent, this.options); } /** * Sets the enabled state of the camera frame. Passing false will release associated resources. * * @type {boolean} */ set enabled(value) { if (this._enabled !== value) { if (value) { this.enable(); } else { this.disable(); } this._enabled = value; } } /** * Gets the enabled state of the camera frame. * * @type {boolean} */ 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; } /** * Applies any changes made to the properties of this instance. */ 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 };