UNPKG

playcanvas

Version:

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

212 lines (211 loc) 6.34 kB
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 };