From 6cbdc515bac2eab1cfd7094681b13af65ae58f8e Mon Sep 17 00:00:00 2001 From: lvisei Date: Thu, 9 May 2024 17:31:07 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=20TAA=20?= =?UTF-8?q?=E7=AE=97=E6=B3=95=E5=90=8E=E5=A4=84=E7=90=86=E6=8A=97=E9=94=AF?= =?UTF-8?q?=E9=BD=BF=E9=80=BB=E8=BE=91=20(#2448)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/inversify.config.ts | 2 - .../core/src/services/camera/CameraService.ts | 40 +-- .../src/services/camera/ICameraService.ts | 2 - .../core/src/services/config/ConfigService.ts | 2 - .../core/src/services/layer/ILayerService.ts | 8 - .../src/services/renderer/passes/TAAPass.ts | 327 ------------------ .../src/shaders/post-processing/blend.glsl | 13 - packages/layers/src/core/BaseLayer.ts | 3 - packages/layers/src/utils/multiPassRender.ts | 10 +- 9 files changed, 4 insertions(+), 403 deletions(-) delete mode 100644 packages/core/src/services/renderer/passes/TAAPass.ts delete mode 100644 packages/core/src/shaders/post-processing/blend.glsl diff --git a/packages/core/src/inversify.config.ts b/packages/core/src/inversify.config.ts index 373c54e4964..e2c766c45c4 100644 --- a/packages/core/src/inversify.config.ts +++ b/packages/core/src/inversify.config.ts @@ -45,7 +45,6 @@ import MultiPassRenderer from './services/renderer/passes/MultiPassRenderer'; import PixelPickingPass from './services/renderer/passes/PixelPickingPass'; import PostProcessor from './services/renderer/passes/PostProcessor'; import RenderPass from './services/renderer/passes/RenderPass'; -import TAAPass from './services/renderer/passes/TAAPass'; import BloomPass from './services/renderer/passes/post-processing/BloomPass'; import BlurHPass from './services/renderer/passes/post-processing/BlurHPass'; import BlurVPass from './services/renderer/passes/post-processing/BlurVPass'; @@ -133,7 +132,6 @@ export function createSceneContainer(): L7Container { clear: new ClearPass(), pixelPicking: new PixelPickingPass(), render: new RenderPass(), - taa: new TAAPass(shaderModuleService), }; container.normalPassFactory = (named: string) => { return normalPass[named]; diff --git a/packages/core/src/services/camera/CameraService.ts b/packages/core/src/services/camera/CameraService.ts index 951786cceba..d45cb576672 100644 --- a/packages/core/src/services/camera/CameraService.ts +++ b/packages/core/src/services/camera/CameraService.ts @@ -9,16 +9,6 @@ export default class CameraService implements ICameraService { */ private overridedViewProjectionMatrix: number[] | undefined; - /** - * 抖动后的 VP 矩阵 - */ - private jitteredViewProjectionMatrix: number[] | undefined; - - /** - * 抖动后的 Projection 矩阵 - */ - private jitteredProjectionMatrix: number[] | undefined; - /** * ViewMatrix 逆矩阵,用于计算相机位置 */ @@ -56,8 +46,7 @@ export default class CameraService implements ICameraService { } public getProjectionMatrix(): number[] { - // 优先返回抖动后的 ProjectionMatrix - return this.jitteredProjectionMatrix || this.viewport.getProjectionMatrix(); + return this.viewport.getProjectionMatrix(); } public getModelMatrix(): number[] { @@ -77,11 +66,7 @@ export default class CameraService implements ICameraService { } public getViewProjectionMatrix(): number[] { - return ( - this.overridedViewProjectionMatrix || - this.jitteredViewProjectionMatrix || - this.viewport.getViewProjectionMatrix() - ); + return this.overridedViewProjectionMatrix || this.viewport.getViewProjectionMatrix(); } public getZoom(): number { @@ -115,25 +100,4 @@ export default class CameraService implements ICameraService { public setViewProjectionMatrix(viewProjectionMatrix: number[] | undefined) { this.overridedViewProjectionMatrix = viewProjectionMatrix; } - - public jitterProjectionMatrix(x: number, y: number) { - const translation = mat4.fromTranslation(mat4.create(), [x, y, 0]); - - this.jitteredProjectionMatrix = mat4.multiply( - mat4.create(), - translation, - this.viewport.getProjectionMatrix() as unknown as mat4, - ) as unknown as number[]; - - this.jitteredViewProjectionMatrix = mat4.multiply( - mat4.create(), - this.jitteredProjectionMatrix as unknown as mat4, - this.viewport.getViewMatrix() as unknown as mat4, - ) as unknown as number[]; - } - - public clearJitterProjectionMatrix() { - this.jitteredProjectionMatrix = undefined; - this.jitteredViewProjectionMatrix = undefined; - } } diff --git a/packages/core/src/services/camera/ICameraService.ts b/packages/core/src/services/camera/ICameraService.ts index 6357f7fa844..468e79b31b1 100644 --- a/packages/core/src/services/camera/ICameraService.ts +++ b/packages/core/src/services/camera/ICameraService.ts @@ -31,6 +31,4 @@ export interface ICameraService extends Omit { update(viewport: IViewport): void; getCameraPosition(): number[]; setViewProjectionMatrix(viewProjectionMatrix: number[] | undefined): void; - jitterProjectionMatrix(x: number, y: number): void; - clearJitterProjectionMatrix(): void; } diff --git a/packages/core/src/services/config/ConfigService.ts b/packages/core/src/services/config/ConfigService.ts index 2f0e77917c1..758015b013c 100644 --- a/packages/core/src/services/config/ConfigService.ts +++ b/packages/core/src/services/config/ConfigService.ts @@ -75,8 +75,6 @@ const defaultLayerConfig: Partial = { activeMix: 0, selectColor: 'blue', selectMix: 0, - enableTAA: false, - jitterScale: 1, enableLighting: false, animateOption: { enable: false, diff --git a/packages/core/src/services/layer/ILayerService.ts b/packages/core/src/services/layer/ILayerService.ts index 738a1c4c033..3ace2441b85 100644 --- a/packages/core/src/services/layer/ILayerService.ts +++ b/packages/core/src/services/layer/ILayerService.ts @@ -651,14 +651,6 @@ export interface ILayerConfig { activeColor: string | number[]; activeMix?: number; selectMix?: number; - /** - * 开启 TAA - */ - enableTAA: boolean; - /** - * 相机抖动程度 - */ - jitterScale: number; /** * 开启光照 */ diff --git a/packages/core/src/services/renderer/passes/TAAPass.ts b/packages/core/src/services/renderer/passes/TAAPass.ts deleted file mode 100644 index c119f388d70..00000000000 --- a/packages/core/src/services/renderer/passes/TAAPass.ts +++ /dev/null @@ -1,327 +0,0 @@ -import blendFS from '../../../shaders/post-processing/blend.glsl'; -import copyFS from '../../../shaders/post-processing/copy.glsl'; -import quadVS from '../../../shaders/post-processing/quad.glsl'; -import type { ILayer } from '../../layer/ILayerService'; -import type { IShaderModuleService } from '../../shader/IShaderModuleService'; -import type { IFramebuffer } from '../IFramebuffer'; -import type { IModel, IModelInitializationOptions } from '../IModel'; -import { PassType } from '../IMultiPassRenderer'; -import { gl } from '../gl'; -import BaseNormalPass from './BaseNormalPass'; - -// Generate halton sequence -// https://en.wikipedia.org/wiki/Halton_sequence -function halton(index: number, base: number) { - let result = 0; - let f = 1 / base; - let i = index; - while (i > 0) { - result = result + f * (i % base); - i = Math.floor(i / base); - f = f / base; - } - return result; -} - -// 累加计数器 -let accumulatingId = 1; - -/** - * TAA(Temporal Anti-Aliasing) - * 在需要后处理的场景中(例如 L7 的热力图需要 blur pass、PBR 中的 SSAO 环境光遮蔽),无法使用浏览器内置的 MSAA, - * 只能使用 TAA - * @see https://yuque.antfin-inc.com/yuqi.pyq/fgetpa/ri52hv - */ - -export default class TAAPass< - InitializationOptions = {}, -> extends BaseNormalPass { - constructor(protected readonly shaderModuleService: IShaderModuleService) { - super(); - } - - /** - * 低差异序列 - */ - private haltonSequence: Array<[number, number]> = []; - - /** - * 当前累加任务 ID,例如用户连续拖拽时上一次累加很有可能没有结束,此时在开启新一轮累加之前需要结束掉之前未完成的 - */ - private accumulatingId: number = 0; - - /** - * 每一轮累加中的 frameID - */ - private frame: number = 0; - - /** - * 每一轮累加中的 frame 定时器 - */ - private timer: number | undefined = undefined; - - private sampleRenderTarget: IFramebuffer; - private prevRenderTarget: IFramebuffer; - private outputRenderTarget: IFramebuffer; - private copyRenderTarget: IFramebuffer; - - private blendModel: IModel; - private outputModel: IModel; - private copyModel: IModel; - - public getType() { - return PassType.Normal; - } - - public getName() { - return 'taa'; - } - - public init(layer: ILayer, config?: Partial) { - super.init(layer, config); - - const { createFramebuffer, createTexture2D } = this.rendererService; - this.sampleRenderTarget = createFramebuffer({ - color: createTexture2D({ - width: 1, - height: 1, - wrapS: gl.CLAMP_TO_EDGE, - wrapT: gl.CLAMP_TO_EDGE, - }), - }); - this.prevRenderTarget = createFramebuffer({ - color: createTexture2D({ - width: 1, - height: 1, - wrapS: gl.CLAMP_TO_EDGE, - wrapT: gl.CLAMP_TO_EDGE, - }), - }); - this.outputRenderTarget = createFramebuffer({ - color: createTexture2D({ - width: 1, - height: 1, - wrapS: gl.CLAMP_TO_EDGE, - wrapT: gl.CLAMP_TO_EDGE, - }), - }); - this.copyRenderTarget = createFramebuffer({ - color: createTexture2D({ - width: 1, - height: 1, - wrapS: gl.CLAMP_TO_EDGE, - wrapT: gl.CLAMP_TO_EDGE, - }), - }); - - for (let i = 0; i < 30; i++) { - this.haltonSequence.push([halton(i, 2), halton(i, 3)]); - } - - this.blendModel = this.createTriangleModel('blend-pass', blendFS); - this.outputModel = this.createTriangleModel('copy-pass', copyFS, { - blend: { - enable: true, - func: { - srcRGB: gl.ONE, - dstRGB: gl.ONE_MINUS_SRC_ALPHA, - srcAlpha: gl.ONE, - dstAlpha: gl.ONE_MINUS_SRC_ALPHA, - }, - equation: { - rgb: gl.FUNC_ADD, - alpha: gl.FUNC_ADD, - }, - }, - }); - this.copyModel = this.createTriangleModel('copy-pass', copyFS); - } - - public render(layer: ILayer) { - const { clear, getViewportSize, useFramebuffer } = this.rendererService; - const { width, height } = getViewportSize(); - this.sampleRenderTarget.resize({ width, height }); - this.prevRenderTarget.resize({ width, height }); - this.outputRenderTarget.resize({ width, height }); - this.copyRenderTarget.resize({ width, height }); - - this.resetFrame(); - // 首先停止上一次的累加 - this.stopAccumulating(); - - // 先输出到 PostProcessor - const readFBO = layer.multiPassRenderer.getPostProcessor().getReadFBO(); - useFramebuffer(readFBO, () => { - clear({ - color: [0, 0, 0, 0], - depth: 1, - stencil: 0, - framebuffer: readFBO, - }); - - // render to post processor - layer.multiPassRenderer.setRenderFlag(false); - layer.render(); - layer.multiPassRenderer.setRenderFlag(true); - }); - - const accumulate = (id: number) => { - // 在开启新一轮累加之前,需要先结束掉之前的累加 - if (!this.accumulatingId || id !== this.accumulatingId) { - return; - } - - if (!this.isFinished()) { - this.doRender(layer); - - window.requestAnimationFrame(() => { - accumulate(id); - }); - } - }; - - this.accumulatingId = accumulatingId++; - // @ts-ignore - this.timer = window.setTimeout(() => { - accumulate(this.accumulatingId); - }, 50); - } - - private doRender(layer: ILayer) { - const { clear, getViewportSize, useFramebuffer } = this.rendererService; - const { width, height } = getViewportSize(); - const { jitterScale = 1 } = layer.getLayerConfig(); - - // 使用 Halton 序列抖动投影矩阵 - const offset = this.haltonSequence[this.frame % this.haltonSequence.length]; - this.cameraService.jitterProjectionMatrix( - ((offset[0] * 2.0 - 1.0) / width) * jitterScale, - ((offset[1] * 2.0 - 1.0) / height) * jitterScale, - ); - - // 按抖动后的投影矩阵渲染 - layer.multiPassRenderer.setRenderFlag(false); - layer.hooks.beforeRender.call(); - useFramebuffer(this.sampleRenderTarget, () => { - clear({ - color: [0, 0, 0, 0], - depth: 1, - stencil: 0, - framebuffer: this.sampleRenderTarget, - }); - - layer.render(); - }); - layer.hooks.afterRender.call(); - layer.multiPassRenderer.setRenderFlag(true); - - // 混合 - const layerStyleOptions = layer.getLayerConfig(); - useFramebuffer(this.outputRenderTarget, () => { - this.blendModel.draw({ - uniforms: { - // @ts-ignore - u_opacity: layerStyleOptions.opacity || 1, - u_MixRatio: this.frame === 0 ? 1 : 0.9, - u_Diffuse1: this.sampleRenderTarget, - u_Diffuse2: - this.frame === 0 - ? layer.multiPassRenderer.getPostProcessor().getReadFBO() - : this.prevRenderTarget, - }, - }); - }); - - // 输出累加结果 - if (this.frame === 0) { - clear({ - color: [0, 0, 0, 0], - depth: 1, - stencil: 0, - framebuffer: this.copyRenderTarget, - }); - } - - if (this.frame >= 1) { - useFramebuffer(this.copyRenderTarget, () => { - this.outputModel.draw({ - uniforms: { - u_Texture: this.outputRenderTarget, - }, - }); - }); - - useFramebuffer(layer.multiPassRenderer.getPostProcessor().getReadFBO(), () => { - this.copyModel.draw({ - uniforms: { - u_Texture: this.copyRenderTarget, - }, - }); - }); - layer.multiPassRenderer.getPostProcessor().render(layer); - } - - // 保存前序帧结果 - const tmp = this.prevRenderTarget; - this.prevRenderTarget = this.outputRenderTarget; - this.outputRenderTarget = tmp; - - this.frame++; - - // 恢复 jitter 后的相机 - this.cameraService.clearJitterProjectionMatrix(); - } - - /** - * 是否已经完成累加 - * @return {boolean} isFinished - */ - private isFinished() { - return this.frame >= this.haltonSequence.length; - } - - private resetFrame() { - this.frame = 0; - } - - private stopAccumulating() { - this.accumulatingId = 0; - window.clearTimeout(this.timer); - } - - private createTriangleModel( - shaderModuleName: string, - fragmentShader: string, - options?: Partial, - ) { - this.shaderModuleService.registerModule(shaderModuleName, { - vs: quadVS, - fs: fragmentShader, - }); - - const { vs, fs, uniforms } = this.shaderModuleService.getModule(shaderModuleName); - const { createAttribute, createBuffer, createModel } = this.rendererService; - return createModel({ - vs, - fs, - attributes: { - // 使用一个全屏三角形,相比 Quad 顶点数目更少 - a_Position: createAttribute({ - buffer: createBuffer({ - data: [-4, -4, 4, -4, 0, 4], - type: gl.FLOAT, - }), - size: 2, - }), - }, - uniforms: { - ...uniforms, - }, - depth: { - enable: false, - }, - count: 3, - ...options, - }); - } -} diff --git a/packages/core/src/shaders/post-processing/blend.glsl b/packages/core/src/shaders/post-processing/blend.glsl deleted file mode 100644 index 2a8cbf98ddf..00000000000 --- a/packages/core/src/shaders/post-processing/blend.glsl +++ /dev/null @@ -1,13 +0,0 @@ -uniform float u_opacity : 1.0; -uniform float u_MixRatio : 0.5; - -uniform sampler2D u_Diffuse1; -uniform sampler2D u_Diffuse2; - -varying vec2 v_UV; - -void main() { - vec4 texel1 = texture2D(u_Diffuse1, v_UV); - vec4 texel2 = texture2D(u_Diffuse2, v_UV); - gl_FragColor = u_opacity * mix(texel1, texel2, u_MixRatio); -} diff --git a/packages/layers/src/core/BaseLayer.ts b/packages/layers/src/core/BaseLayer.ts index 10903d8e741..3b3a1a3d894 100644 --- a/packages/layers/src/core/BaseLayer.ts +++ b/packages/layers/src/core/BaseLayer.ts @@ -736,9 +736,6 @@ export default class BaseLayer if (this.multiPassRenderer && this.multiPassRenderer.getRenderFlag()) { // multi render 开始执行 multiPassRender 的渲染流程 await this.multiPassRenderer.render(); - } else if (this.multiPassRenderer) { - // renderPass 触发的渲染 - this.renderModels(); } else { this.renderModels(); } diff --git a/packages/layers/src/utils/multiPassRender.ts b/packages/layers/src/utils/multiPassRender.ts index f2755434cc5..21155442e62 100644 --- a/packages/layers/src/utils/multiPassRender.ts +++ b/packages/layers/src/utils/multiPassRender.ts @@ -23,20 +23,14 @@ export function createMultiPassRenderer( normalPassFactory: (name: string) => IPass, ) { const multiPassRenderer = layer.multiPassRenderer; - const { enableTAA } = layer.getLayerConfig(); // picking pass if enabled // if (enablePicking) { // multiPassRenderer.add(normalPassFactory('pixelPicking')); // } - // use TAA pass if enabled instead of render pass - if (enableTAA) { - multiPassRenderer.add(normalPassFactory('taa')); - } else { - // render all layers in this pass - multiPassRenderer.add(normalPassFactory('render')); - } + // render all layers in this pass + multiPassRenderer.add(normalPassFactory('render')); // post processing normalizePasses(passes).forEach((pass: [string, { [key: string]: unknown }]) => {