UNPKG

playcanvas

Version:

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

129 lines (128 loc) 4.12 kB
import { Color } from "../../core/math/color.js"; import { Texture } from "../../platform/graphics/texture.js"; import { RenderTarget } from "../../platform/graphics/render-target.js"; import { FramePass } from "../../platform/graphics/frame-pass.js"; import { FILTER_LINEAR, ADDRESS_CLAMP_TO_EDGE, PIXELFORMAT_RG8, PIXELFORMAT_R8 } from "../../platform/graphics/constants.js"; import { RenderPassDownsample } from "./render-pass-downsample.js"; import { RenderPassCoC } from "./render-pass-coc.js"; import { RenderPassDofBlur } from "./render-pass-dof-blur.js"; class FramePassDof extends FramePass { focusDistance = 100; focusRange = 50; blurRadius = 1; blurRings = 3; blurRingPoints = 3; highQuality = true; cocTexture = null; blurTexture = null; cocPass = null; farPass = null; blurPass = null; constructor(device, cameraComponent, sceneTexture, sceneTextureHalf, highQuality, nearBlur) { super(device); this.highQuality = highQuality; this.cocPass = this.setupCocPass(device, cameraComponent, sceneTexture, nearBlur); this.beforePasses.push(this.cocPass); const sourceTexture = highQuality ? sceneTexture : sceneTextureHalf; this.farPass = this.setupFarPass(device, sourceTexture, 0.5); this.beforePasses.push(this.farPass); this.blurPass = this.setupBlurPass(device, sceneTextureHalf, nearBlur, highQuality ? 2 : 0.5); this.beforePasses.push(this.blurPass); } destroy() { this.destroyRenderPasses(); this.cocPass = null; this.farPass = null; this.blurPass = null; this.destroyRT(this.cocRT); this.destroyRT(this.farRt); this.destroyRT(this.blurRt); this.cocRT = null; this.farRt = null; this.blurRt = null; } destroyRenderPasses() { for (let i = 0; i < this.beforePasses.length; i++) { this.beforePasses[i].destroy(); } this.beforePasses.length = 0; } destroyRT(rt) { if (rt) { rt.destroyTextureBuffers(); rt.destroy(); } } setupCocPass(device, cameraComponent, sourceTexture, nearBlur) { const format = nearBlur ? PIXELFORMAT_RG8 : PIXELFORMAT_R8; this.cocRT = this.createRenderTarget("CoCTexture", format); this.cocTexture = this.cocRT.colorBuffer; const cocPass = new RenderPassCoC(device, cameraComponent, nearBlur); cocPass.init(this.cocRT, { resizeSource: sourceTexture }); cocPass.setClearColor(Color.BLACK); return cocPass; } setupFarPass(device, sourceTexture, scale) { this.farRt = this.createRenderTarget("FarDofTexture", sourceTexture.format); const farPass = new RenderPassDownsample(device, sourceTexture, { boxFilter: true, premultiplyTexture: this.cocTexture, premultiplySrcChannel: "r" // far CoC }); farPass.init(this.farRt, { resizeSource: sourceTexture, scaleX: scale, scaleY: scale }); farPass.setClearColor(Color.BLACK); return farPass; } setupBlurPass(device, nearTexture, nearBlur, scale) { const farTexture = this.farRt?.colorBuffer; this.blurRt = this.createRenderTarget("DofBlurTexture", nearTexture.format); this.blurTexture = this.blurRt.colorBuffer; const blurPass = new RenderPassDofBlur(device, nearBlur ? nearTexture : null, farTexture, this.cocTexture); blurPass.init(this.blurRt, { resizeSource: nearTexture, scaleX: scale, scaleY: scale }); blurPass.setClearColor(Color.BLACK); return blurPass; } createTexture(name, format) { return new Texture(this.device, { name, width: 1, height: 1, format, mipmaps: false, minFilter: FILTER_LINEAR, magFilter: FILTER_LINEAR, addressU: ADDRESS_CLAMP_TO_EDGE, addressV: ADDRESS_CLAMP_TO_EDGE }); } createRenderTarget(name, format) { return new RenderTarget({ colorBuffer: this.createTexture(name, format), depth: false, stencil: false }); } frameUpdate() { super.frameUpdate(); this.cocPass.focusDistance = this.focusDistance; this.cocPass.focusRange = this.focusRange; this.blurPass.blurRadiusNear = this.blurRadius; this.blurPass.blurRadiusFar = this.blurRadius * (this.highQuality ? 1 : 0.5); this.blurPass.blurRings = this.blurRings; this.blurPass.blurRingPoints = this.blurRingPoints; } } export { FramePassDof };