diff --git a/editor/assets/default_renderpipeline/builtin-bloom-pass.ts b/editor/assets/default_renderpipeline/builtin-bloom-pass.ts deleted file mode 100644 index c93e5c26a29..00000000000 --- a/editor/assets/default_renderpipeline/builtin-bloom-pass.ts +++ /dev/null @@ -1,326 +0,0 @@ -/* - Copyright (c) 2021-2024 Xiamen Yaji Software Co., Ltd. - - https://www.cocos.com/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -import { - _decorator, assert, CCBoolean, CCFloat, CCInteger, - gfx, Material, renderer, rendering, Vec4, -} from 'cc'; - -import { EDITOR } from 'cc/env'; - -import { - BuiltinPipelineSettings, -} from './builtin-pipeline-settings'; - -import { - BuiltinPipelinePassBuilder, -} from './builtin-pipeline-pass'; - -import { - addCopyToScreenPass, - CameraConfigs, - PipelineConfigs, - PipelineContext, -} from './builtin-pipeline'; - -const { ccclass, disallowMultiple, executeInEditMode, menu, property, requireComponent } = _decorator; - -const { Color, LoadOp, StoreOp } = gfx; - -export interface BloomPassConfigs { - enableBloom: boolean; -} - -@ccclass('BuiltinBloomPass') -@menu('Rendering/BuiltinBloomPass') -@requireComponent(BuiltinPipelineSettings) -@disallowMultiple -@executeInEditMode -export class BuiltinBloomPass extends BuiltinPipelinePassBuilder - implements rendering.PipelinePassBuilder { - @property({ - group: { id: 'BuiltinPass', name: 'Pass Settings', style: 'section' }, - type: CCInteger, - }) - configOrder = 0; - @property({ - group: { id: 'BuiltinPass', name: 'Pass Settings', style: 'section' }, - type: CCInteger, - }) - renderOrder = 200; - - @property - protected _bloomEnable = true; - @property - protected _bloomMaterial: Material | null = null; - @property - protected _bloomEnableAlphaMask = false; - @property - protected _bloomIterations = 3; - @property - protected _bloomThreshold = 0.8; - @property - protected _bloomIntensity = 2.3; - - // Bloom - @property({ - group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' }, - type: CCBoolean, - }) - set bloomEnable(value: boolean) { - this._bloomEnable = value; - if (EDITOR) { - this._parent._tryEnableEditorPreview(); - } - } - get bloomEnable(): boolean { - return this._bloomEnable; - } - - @property({ - group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' }, - type: Material, - }) - set bloomMaterial(value: Material) { - if (this._bloomMaterial === value) { - return; - } - this._bloomMaterial = value; - if (EDITOR) { - this._parent._tryEnableEditorPreview(); - } - } - get bloomMaterial(): Material { - return this._bloomMaterial!; - } - - @property({ - tooltip: 'i18n:bloom.enableAlphaMask', - group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' }, - type: CCBoolean, - }) - set bloomEnableAlphaMask(value: boolean) { - this._bloomEnableAlphaMask = value; - if (EDITOR) { - this._parent._tryEnableEditorPreview(); - } - } - get bloomEnableAlphaMask(): boolean { - return this._bloomEnableAlphaMask; - } - - @property({ - tooltip: 'i18n:bloom.iterations', - group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' }, - type: CCInteger, - range: [1, 6, 1], - slide: true, - }) - set bloomIterations(value: number) { - this._bloomIterations = value; - if (EDITOR) { - this._parent._tryEnableEditorPreview(); - } - } - get bloomIterations(): number { - return this._bloomIterations; - } - - @property({ - tooltip: 'i18n:bloom.threshold', - group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' }, - type: CCFloat, - min: 0, - }) - set bloomThreshold(value: number) { - this._bloomThreshold = value; - } - get bloomThreshold(): number { - return this._bloomThreshold; - } - - set bloomIntensity(value: number) { - this._bloomIntensity = value; - } - get bloomIntensity(): number { - return this._bloomIntensity; - } - - configCamera( - camera: Readonly, - pipelineConfigs: Readonly, - cameraConfigs: CameraConfigs & BloomPassConfigs): void { - cameraConfigs.enableBloom = this._bloomEnable && !!this._bloomMaterial; - if (cameraConfigs.enableBloom) { - ++cameraConfigs.remainingPasses; - } - } - windowResize( - ppl: rendering.BasicPipeline, - pplConfigs: Readonly, - cameraConfigs: CameraConfigs & BloomPassConfigs, - window: renderer.RenderWindow): void { - if (cameraConfigs.enableBloom) { - const id = window.renderWindowId; - let bloomWidth = cameraConfigs.width; - let bloomHeight = cameraConfigs.height; - for (let i = 0; i !== this._bloomIterations + 1; ++i) { - bloomWidth = Math.max(Math.floor(bloomWidth / 2), 1); - bloomHeight = Math.max(Math.floor(bloomHeight / 2), 1); - ppl.addRenderTarget(`BloomTex${id}_${i}`, - cameraConfigs.radianceFormat, bloomWidth, bloomHeight); - } - } - } - setup( - ppl: rendering.BasicPipeline, - pplConfigs: Readonly, - cameraConfigs: CameraConfigs & BloomPassConfigs, - camera: renderer.scene.Camera, - context: PipelineContext, - prevRenderPass?: rendering.BasicRenderPassBuilder) - : rendering.BasicRenderPassBuilder | undefined { - if (!cameraConfigs.enableBloom) { - return prevRenderPass; - } - - --cameraConfigs.remainingPasses; - assert(cameraConfigs.remainingPasses >= 0); - const id = camera.window.renderWindowId; - assert(!!this._bloomMaterial); - return this._addKawaseDualFilterBloomPasses( - ppl, pplConfigs, - cameraConfigs, - id, - cameraConfigs.width, - cameraConfigs.height, - context.colorName); - } - - private _addKawaseDualFilterBloomPasses( - ppl: rendering.BasicPipeline, - pplConfigs: Readonly, - cameraConfigs: CameraConfigs & Readonly, - id: number, - width: number, - height: number, - radianceName: string, - ): rendering.BasicRenderPassBuilder { - assert(!!this._bloomMaterial); - const QueueHint = rendering.QueueHint; - // Based on Kawase Dual Filter Blur. Saves bandwidth on mobile devices. - // eslint-disable-next-line max-len - // https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_slides.pdf - - // Size: [prefilter(1/2), downsample(1/4), downsample(1/8), downsample(1/16), ...] - const iterations = this._bloomIterations; - const sizeCount = iterations + 1; - this._bloomWidths.length = sizeCount; - this._bloomHeights.length = sizeCount; - this._bloomWidths[0] = Math.max(Math.floor(width / 2), 1); - this._bloomHeights[0] = Math.max(Math.floor(height / 2), 1); - for (let i = 1; i !== sizeCount; ++i) { - this._bloomWidths[i] = Math.max(Math.floor(this._bloomWidths[i - 1] / 2), 1); - this._bloomHeights[i] = Math.max(Math.floor(this._bloomHeights[i - 1] / 2), 1); - } - - // Bloom texture names - this._bloomTexNames.length = sizeCount; - for (let i = 0; i !== sizeCount; ++i) { - this._bloomTexNames[i] = `BloomTex${id}_${i}`; - } - - // Setup bloom parameters - this._bloomParams.x = pplConfigs.useFloatOutput ? 1 : 0; - this._bloomParams.x = 0; // unused - this._bloomParams.z = this._bloomThreshold; - this._bloomParams.w = this._bloomEnableAlphaMask ? 1 : 0; - - // Prefilter pass - const prefilterPass = ppl.addRenderPass(this._bloomWidths[0], this._bloomHeights[0], 'cc-bloom-prefilter'); - prefilterPass.addRenderTarget( - this._bloomTexNames[0], - LoadOp.CLEAR, - StoreOp.STORE, - this._clearColorTransparentBlack, - ); - prefilterPass.addTexture(radianceName, 'inputTexture'); - prefilterPass.setVec4('g_platform', pplConfigs.platform); - prefilterPass.setVec4('bloomParams', this._bloomParams); - prefilterPass - .addQueue(QueueHint.OPAQUE) - .addFullscreenQuad(this._bloomMaterial, 0); - - // Downsample passes - for (let i = 1; i !== sizeCount; ++i) { - const downPass = ppl.addRenderPass(this._bloomWidths[i], this._bloomHeights[i], 'cc-bloom-downsample'); - downPass.addRenderTarget(this._bloomTexNames[i], LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); - downPass.addTexture(this._bloomTexNames[i - 1], 'bloomTexture'); - this._bloomTexSize.x = this._bloomWidths[i - 1]; - this._bloomTexSize.y = this._bloomHeights[i - 1]; - downPass.setVec4('g_platform', pplConfigs.platform); - downPass.setVec4('bloomTexSize', this._bloomTexSize); - downPass - .addQueue(QueueHint.OPAQUE) - .addFullscreenQuad(this._bloomMaterial, 1); - } - - // Upsample passes - for (let i = iterations; i-- > 0;) { - const upPass = ppl.addRenderPass(this._bloomWidths[i], this._bloomHeights[i], 'cc-bloom-upsample'); - upPass.addRenderTarget(this._bloomTexNames[i], LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); - upPass.addTexture(this._bloomTexNames[i + 1], 'bloomTexture'); - this._bloomTexSize.x = this._bloomWidths[i + 1]; - this._bloomTexSize.y = this._bloomHeights[i + 1]; - upPass.setVec4('g_platform', pplConfigs.platform); - upPass.setVec4('bloomTexSize', this._bloomTexSize); - upPass - .addQueue(QueueHint.OPAQUE) - .addFullscreenQuad(this._bloomMaterial, 2); - } - - // Combine pass - const combinePass = ppl.addRenderPass(width, height, 'cc-bloom-combine'); - combinePass.addRenderTarget(radianceName, LoadOp.LOAD, StoreOp.STORE); - combinePass.addTexture(this._bloomTexNames[0], 'bloomTexture'); - combinePass.setVec4('g_platform', pplConfigs.platform); - combinePass.setVec4('bloomParams', this._bloomParams); - combinePass - .addQueue(QueueHint.BLEND) - .addFullscreenQuad(this._bloomMaterial, 3); - - if (cameraConfigs.remainingPasses === 0) { - return addCopyToScreenPass(ppl, pplConfigs, cameraConfigs, radianceName); - } else { - return combinePass; - } - } - // Bloom - private readonly _clearColorTransparentBlack = new Color(0, 0, 0, 0); - private readonly _bloomParams = new Vec4(0, 0, 0, 0); - private readonly _bloomTexSize = new Vec4(0, 0, 0, 0); - private readonly _bloomWidths: Array = []; - private readonly _bloomHeights: Array = []; - private readonly _bloomTexNames: Array = []; -} diff --git a/editor/assets/default_renderpipeline/builtin-bloom-pass.ts.meta b/editor/assets/default_renderpipeline/builtin-bloom-pass.ts.meta deleted file mode 100644 index b3d30c396a9..00000000000 --- a/editor/assets/default_renderpipeline/builtin-bloom-pass.ts.meta +++ /dev/null @@ -1,9 +0,0 @@ -{ - "ver": "4.0.24", - "importer": "typescript", - "imported": true, - "uuid": "5b9314e6-8955-435d-a14f-c8f2cdcdac44", - "files": [], - "subMetas": {}, - "userData": {} -} diff --git a/editor/assets/default_renderpipeline/builtin-dof-pass.ts b/editor/assets/default_renderpipeline/builtin-dof-pass.ts index 97fa7d451f8..11a6ab56f42 100644 --- a/editor/assets/default_renderpipeline/builtin-dof-pass.ts +++ b/editor/assets/default_renderpipeline/builtin-dof-pass.ts @@ -71,19 +71,19 @@ export class BuiltinDepthOfFieldPass extends BuiltinPipelinePassBuilder renderOrder = 150; @property - protected _enableDof = false; + private _enableDof = false; @property - protected _material: Material | null = null; + private _material: Material | null = null; @property - protected _minRange = 0; + private _minRange = 0; @property - protected _maxRange = 2; + private _maxRange = 2; @property - protected _blurRadius = 1; + private _blurRadius = 1; @property - protected _intensity = 1; + private _intensity = 1; @property - protected _focusPos = new Vec3(0, 0, 0); + private _focusPos = new Vec3(0, 0, 0); // DepthOfField @property({ diff --git a/editor/assets/default_renderpipeline/builtin-fsr-pass.ts b/editor/assets/default_renderpipeline/builtin-fsr-pass.ts deleted file mode 100644 index c670664dc6a..00000000000 --- a/editor/assets/default_renderpipeline/builtin-fsr-pass.ts +++ /dev/null @@ -1,218 +0,0 @@ -/* - Copyright (c) 2021-2024 Xiamen Yaji Software Co., Ltd. - - https://www.cocos.com/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -import { - _decorator, assert, CCBoolean, CCFloat, CCInteger, - clamp, - gfx, Material, renderer, rendering, Vec4, -} from 'cc'; - -import { EDITOR } from 'cc/env'; - -import { - BuiltinPipelineSettings, -} from './builtin-pipeline-settings'; - -import { - BuiltinPipelinePassBuilder, -} from './builtin-pipeline-pass'; - -import { - CameraConfigs, - getPingPongRenderTarget, - PipelineConfigs, - PipelineContext, -} from './builtin-pipeline'; - -const { ccclass, disallowMultiple, executeInEditMode, menu, property, requireComponent } = _decorator; - -const { Color, LoadOp, StoreOp } = gfx; - -export interface FSRPassConfigs { - enableFSR: boolean; -} - -@ccclass('BuiltinFSRPass') -@menu('Rendering/BuiltinFSRPass') -@requireComponent(BuiltinPipelineSettings) -@disallowMultiple -@executeInEditMode -export class BuiltinFSRPass extends BuiltinPipelinePassBuilder - implements rendering.PipelinePassBuilder { - @property({ - group: { id: 'BuiltinPass', name: 'Pass Settings', style: 'section' }, - type: CCInteger, - }) - configOrder = 0; - @property({ - group: { id: 'BuiltinPass', name: 'Pass Settings', style: 'section' }, - type: CCInteger, - }) - renderOrder = 500; - - @property - protected _fsrEnable = true; - @property - protected _fsrMaterial: Material | null = null; - @property - protected _fsrSharpness = 0.8; - - // FSR - @property({ - group: { id: 'FSR', name: 'FidelityFX Super Resolution', style: 'section' }, - type: CCBoolean, - }) - set fsrEnable(value: boolean) { - this._fsrEnable = value; - if (EDITOR) { - this._parent._tryEnableEditorPreview(); - } - } - get fsrEnable(): boolean { - return this._fsrEnable; - } - - @property({ - group: { id: 'FSR', name: 'FidelityFX Super Resolution', style: 'section' }, - type: Material, - }) - set fsrMaterial(value: Material) { - if (this._fsrMaterial === value) { - return; - } - this._fsrMaterial = value; - if (EDITOR) { - this._parent._tryEnableEditorPreview(); - } - } - get fsrMaterial(): Material { - return this._fsrMaterial!; - } - - @property({ - group: { id: 'FSR', name: 'FidelityFX Super Resolution', style: 'section' }, - type: CCFloat, - range: [0, 1, 0.01], - slide: true, - }) - set fsrSharpness(value: number) { - this._fsrSharpness = value; - } - get fsrSharpness(): number { - return this._fsrSharpness; - } - - configCamera( - camera: Readonly, - pplConfigs: Readonly, - cameraConfigs: CameraConfigs & FSRPassConfigs): void { - // FSR (Depend on Shading scale) - cameraConfigs.enableFSR = this._fsrEnable - && !!this._fsrMaterial - && cameraConfigs.enableShadingScale - && cameraConfigs.shadingScale < 1.0; - - if (cameraConfigs.enableFSR) { - ++cameraConfigs.remainingPasses; - } - } - setup( - ppl: rendering.BasicPipeline, - pplConfigs: Readonly, - cameraConfigs: CameraConfigs & FSRPassConfigs, - camera: renderer.scene.Camera, - context: PipelineContext, - prevRenderPass?: rendering.BasicRenderPassBuilder) - : rendering.BasicRenderPassBuilder | undefined { - if (!cameraConfigs.enableFSR) { - return prevRenderPass; - } - --cameraConfigs.remainingPasses; - - const inputColorName = context.colorName; - const outputColorName - = cameraConfigs.remainingPasses === 0 - ? cameraConfigs.colorName - : getPingPongRenderTarget(context.colorName, 'UiColor', cameraConfigs.renderWindowId); - context.colorName = outputColorName; - - assert(!!this._fsrMaterial); - return this._addFsrPass(ppl, pplConfigs, cameraConfigs, - cameraConfigs.renderWindowId, - cameraConfigs.width, - cameraConfigs.height, - inputColorName, - cameraConfigs.nativeWidth, - cameraConfigs.nativeHeight, - outputColorName); - } - private _addFsrPass( - ppl: rendering.BasicPipeline, - pplConfigs: Readonly, - cameraConfigs: CameraConfigs & FSRPassConfigs, - id: number, - width: number, - height: number, - inputColorName: string, - nativeWidth: number, - nativeHeight: number, - outputColorName: string, - ): rendering.BasicRenderPassBuilder { - assert(!!this._fsrMaterial); - this._fsrTexSize.x = width; - this._fsrTexSize.y = height; - this._fsrTexSize.z = nativeWidth; - this._fsrTexSize.w = nativeHeight; - this._fsrParams.x = clamp(1.0 - this._fsrSharpness, 0.02, 0.98); - - const uiColorPrefix = 'UiColor'; - - const fsrColorName = getPingPongRenderTarget(outputColorName, uiColorPrefix, id); - - const easuPass = ppl.addRenderPass(nativeWidth, nativeHeight, 'cc-fsr-easu'); - easuPass.addRenderTarget(fsrColorName, LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); - easuPass.addTexture(inputColorName, 'outputResultMap'); - easuPass.setVec4('g_platform', pplConfigs.platform); - easuPass.setVec4('fsrTexSize', this._fsrTexSize); - easuPass - .addQueue(rendering.QueueHint.OPAQUE) - .addFullscreenQuad(this._fsrMaterial, 0); - - const rcasPass = ppl.addRenderPass(nativeWidth, nativeHeight, 'cc-fsr-rcas'); - rcasPass.addRenderTarget(outputColorName, LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); - rcasPass.addTexture(fsrColorName, 'outputResultMap'); - rcasPass.setVec4('g_platform', pplConfigs.platform); - rcasPass.setVec4('fsrTexSize', this._fsrTexSize); - rcasPass.setVec4('fsrParams', this._fsrParams); - rcasPass - .addQueue(rendering.QueueHint.OPAQUE) - .addFullscreenQuad(this._fsrMaterial, 1); - - return rcasPass; - } - // FSR - private readonly _clearColorTransparentBlack = new Color(0, 0, 0, 0); - private readonly _fsrParams = new Vec4(0, 0, 0, 0); - private readonly _fsrTexSize = new Vec4(0, 0, 0, 0); -} diff --git a/editor/assets/default_renderpipeline/builtin-fsr-pass.ts.meta b/editor/assets/default_renderpipeline/builtin-fsr-pass.ts.meta deleted file mode 100644 index e7557ab6c13..00000000000 --- a/editor/assets/default_renderpipeline/builtin-fsr-pass.ts.meta +++ /dev/null @@ -1,9 +0,0 @@ -{ - "ver": "4.0.24", - "importer": "typescript", - "imported": true, - "uuid": "38163f91-9a44-4b7f-80cf-7876bb754bd4", - "files": [], - "subMetas": {}, - "userData": {} -} diff --git a/editor/assets/default_renderpipeline/builtin-fxaa-pass.ts b/editor/assets/default_renderpipeline/builtin-fxaa-pass.ts deleted file mode 100644 index d3a4b19693f..00000000000 --- a/editor/assets/default_renderpipeline/builtin-fxaa-pass.ts +++ /dev/null @@ -1,198 +0,0 @@ -/* - Copyright (c) 2021-2024 Xiamen Yaji Software Co., Ltd. - - https://www.cocos.com/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -import { - _decorator, assert, CCBoolean, CCInteger, - gfx, Material, renderer, rendering, Vec4, -} from 'cc'; - -import { EDITOR } from 'cc/env'; - -import { - BuiltinPipelineSettings, -} from './builtin-pipeline-settings'; - -import { - BuiltinPipelinePassBuilder, -} from './builtin-pipeline-pass'; - -import { - addCopyToScreenPass, - CameraConfigs, - getPingPongRenderTarget, - PipelineConfigs, - PipelineContext, -} from './builtin-pipeline'; - -const { ccclass, disallowMultiple, executeInEditMode, menu, property, requireComponent } = _decorator; - -const { Color, LoadOp, StoreOp } = gfx; - -export interface FXAAPassConfigs { - enableFXAA: boolean; -} - -@ccclass('BuiltinFXAAPass') -@menu('Rendering/BuiltinFXAAPass') -@requireComponent(BuiltinPipelineSettings) -@disallowMultiple -@executeInEditMode -export class BuiltinFXAAPass extends BuiltinPipelinePassBuilder - implements rendering.PipelinePassBuilder { - @property({ - group: { id: 'BuiltinPass', name: 'Pass Settings', style: 'section' }, - type: CCInteger, - }) - configOrder = 0; - @property({ - group: { id: 'BuiltinPass', name: 'Pass Settings', style: 'section' }, - type: CCInteger, - }) - renderOrder = 400; - - @property - protected _fxaaEnable = true; - @property - protected _fxaaMaterial: Material | null = null; - - // FXAA - @property({ - group: { id: 'FXAA', name: 'Fast Approximate Anti-Aliasing (PostProcessing)', style: 'section' }, - type: CCBoolean, - }) - set fxaaEnable(value: boolean) { - this._fxaaEnable = value; - if (EDITOR) { - this._parent._tryEnableEditorPreview(); - } - } - get fxaaEnable(): boolean { - return this._fxaaEnable; - } - - @property({ - group: { id: 'FXAA', name: 'Fast Approximate Anti-Aliasing (PostProcessing)', style: 'section' }, - type: Material, - }) - set fxaaMaterial(value: Material) { - if (this._fxaaMaterial === value) { - return; - } - this._fxaaMaterial = value; - if (EDITOR) { - this._parent._tryEnableEditorPreview(); - } - } - get fxaaMaterial(): Material { - return this._fxaaMaterial!; - } - - configCamera( - camera: Readonly, - pplConfigs: Readonly, - cameraConfigs: CameraConfigs & FXAAPassConfigs): void { - cameraConfigs.enableFXAA = this._fxaaEnable && !!this._fxaaMaterial; - if (cameraConfigs.enableFXAA) { - ++cameraConfigs.remainingPasses; - } - } - setup( - ppl: rendering.BasicPipeline, - pplConfigs: Readonly, - cameraConfigs: CameraConfigs & FXAAPassConfigs, - camera: renderer.scene.Camera, - context: PipelineContext, - prevRenderPass?: rendering.BasicRenderPassBuilder) - : rendering.BasicRenderPassBuilder | undefined { - if (!cameraConfigs.enableFXAA) { - return prevRenderPass; - } - --cameraConfigs.remainingPasses; - assert(cameraConfigs.remainingPasses >= 0); - - const id = cameraConfigs.renderWindowId; - const ldrColorPrefix = cameraConfigs.enableShadingScale - ? `ScaledLdrColor` - : `LdrColor`; - const ldrColorName = getPingPongRenderTarget(context.colorName, ldrColorPrefix, id); - - assert(!!this._fxaaMaterial); - if (cameraConfigs.remainingPasses === 0) { - if (cameraConfigs.enableShadingScale) { - this._addFxaaPass(ppl, pplConfigs, - this._fxaaMaterial, - cameraConfigs.width, - cameraConfigs.height, - context.colorName, - ldrColorName); - return addCopyToScreenPass(ppl, pplConfigs, cameraConfigs, ldrColorName); - } else { - assert(cameraConfigs.width === cameraConfigs.nativeWidth); - assert(cameraConfigs.height === cameraConfigs.nativeHeight); - return this._addFxaaPass(ppl, pplConfigs, - this._fxaaMaterial, - cameraConfigs.width, - cameraConfigs.height, - context.colorName, - cameraConfigs.colorName); - } - } else { - const inputColorName = context.colorName; - context.colorName = ldrColorName; - const lastPass = this._addFxaaPass(ppl, pplConfigs, - this._fxaaMaterial, - cameraConfigs.width, - cameraConfigs.height, - inputColorName, - ldrColorName); - return lastPass; - } - } - private _addFxaaPass( - ppl: rendering.BasicPipeline, - pplConfigs: Readonly, - fxaaMaterial: Material, - width: number, - height: number, - ldrColorName: string, - colorName: string, - ): rendering.BasicRenderPassBuilder { - this._fxaaParams.x = width; - this._fxaaParams.y = height; - this._fxaaParams.z = 1 / width; - this._fxaaParams.w = 1 / height; - - const pass = ppl.addRenderPass(width, height, 'cc-fxaa'); - pass.addRenderTarget(colorName, LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); - pass.addTexture(ldrColorName, 'sceneColorMap'); - pass.setVec4('g_platform', pplConfigs.platform); - pass.setVec4('texSize', this._fxaaParams); - pass.addQueue(rendering.QueueHint.OPAQUE) - .addFullscreenQuad(fxaaMaterial, 0); - return pass; - } - // FXAA - private readonly _fxaaParams = new Vec4(0, 0, 0, 0); - private readonly _clearColorTransparentBlack = new Color(0, 0, 0, 0); -} diff --git a/editor/assets/default_renderpipeline/builtin-fxaa-pass.ts.meta b/editor/assets/default_renderpipeline/builtin-fxaa-pass.ts.meta deleted file mode 100644 index 29ad07f79e3..00000000000 --- a/editor/assets/default_renderpipeline/builtin-fxaa-pass.ts.meta +++ /dev/null @@ -1,9 +0,0 @@ -{ - "ver": "4.0.24", - "importer": "typescript", - "imported": true, - "uuid": "bf9cf942-7180-4596-8da8-bfa3b95082c0", - "files": [], - "subMetas": {}, - "userData": {} -} diff --git a/editor/assets/default_renderpipeline/builtin-pipeline-settings.ts b/editor/assets/default_renderpipeline/builtin-pipeline-settings.ts index a8d82d3063f..c4bc43f9990 100644 --- a/editor/assets/default_renderpipeline/builtin-pipeline-settings.ts +++ b/editor/assets/default_renderpipeline/builtin-pipeline-settings.ts @@ -33,7 +33,7 @@ import { fillRequiredPipelineSettings, makePipelineSettings, PipelineSettings, } from './builtin-pipeline-types'; -const { ccclass, disallowMultiple, executeInEditMode, menu, property, requireComponent } = _decorator; +const { ccclass, disallowMultiple, executeInEditMode, menu, property, requireComponent, type } = _decorator; @ccclass('BuiltinPipelineSettings') @menu('Rendering/BuiltinPipelineSettings') @@ -170,6 +170,90 @@ export class BuiltinPipelineSettings extends Component { return this._settings.shadingScale; } + // Bloom + @property({ + group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' }, + type: CCBoolean, + }) + set bloomEnable(value: boolean) { + this._settings.bloom.enabled = value; + if (EDITOR) { + this._tryEnableEditorPreview(); + } + } + get bloomEnable(): boolean { + return this._settings.bloom.enabled; + } + + @property({ + group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' }, + type: Material, + }) + set bloomMaterial(value: Material) { + if (this._settings.bloom.material === value) { + return; + } + this._settings.bloom.material = value; + if (EDITOR) { + this._tryEnableEditorPreview(); + } + } + get bloomMaterial(): Material { + return this._settings.bloom.material!; + } + + @property({ + tooltip: 'i18n:bloom.enableAlphaMask', + group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' }, + type: CCBoolean, + }) + set bloomEnableAlphaMask(value: boolean) { + this._settings.bloom.enableAlphaMask = value; + if (EDITOR) { + this._tryEnableEditorPreview(); + } + } + get bloomEnableAlphaMask(): boolean { + return this._settings.bloom.enableAlphaMask; + } + + @property({ + tooltip: 'i18n:bloom.iterations', + group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' }, + type: CCInteger, + range: [1, 6, 1], + slide: true, + }) + set bloomIterations(value: number) { + this._settings.bloom.iterations = value; + if (EDITOR) { + this._tryEnableEditorPreview(); + } + } + get bloomIterations(): number { + return this._settings.bloom.iterations; + } + + @property({ + tooltip: 'i18n:bloom.threshold', + group: { id: 'Bloom', name: 'Bloom (PostProcessing)', style: 'section' }, + type: CCFloat, + min: 0, + }) + set bloomThreshold(value: number) { + this._settings.bloom.threshold = value; + } + get bloomThreshold(): number { + return this._settings.bloom.threshold; + } + + set bloomIntensity(value: number) { + this._settings.bloom.intensity = value; + } + get bloomIntensity(): number { + return this._settings.bloom.intensity; + } + // Color Grading (LDR) @property({ group: { id: 'Color Grading', name: 'ColorGrading (LDR) (PostProcessing)', style: 'section' }, @@ -231,6 +315,83 @@ export class BuiltinPipelineSettings extends Component { return this._settings.colorGrading.colorGradingMap!; } + // FXAA + @property({ + group: { id: 'FXAA', name: 'Fast Approximate Anti-Aliasing (PostProcessing)', style: 'section' }, + type: CCBoolean, + }) + set fxaaEnable(value: boolean) { + this._settings.fxaa.enabled = value; + if (EDITOR) { + this._tryEnableEditorPreview(); + } + } + get fxaaEnable(): boolean { + return this._settings.fxaa.enabled; + } + + @property({ + group: { id: 'FXAA', name: 'Fast Approximate Anti-Aliasing (PostProcessing)', style: 'section' }, + type: Material, + }) + set fxaaMaterial(value: Material) { + if (this._settings.fxaa.material === value) { + return; + } + this._settings.fxaa.material = value; + if (EDITOR) { + this._tryEnableEditorPreview(); + } + } + get fxaaMaterial(): Material { + return this._settings.fxaa.material!; + } + + // FSR + @property({ + group: { id: 'FSR', name: 'FidelityFX Super Resolution', style: 'section' }, + type: CCBoolean, + }) + set fsrEnable(value: boolean) { + this._settings.fsr.enabled = value; + if (EDITOR) { + this._tryEnableEditorPreview(); + } + } + get fsrEnable(): boolean { + return this._settings.fsr.enabled; + } + + @property({ + group: { id: 'FSR', name: 'FidelityFX Super Resolution', style: 'section' }, + type: Material, + }) + set fsrMaterial(value: Material) { + if (this._settings.fsr.material === value) { + return; + } + this._settings.fsr.material = value; + if (EDITOR) { + this._tryEnableEditorPreview(); + } + } + get fsrMaterial(): Material { + return this._settings.fsr.material!; + } + + @property({ + group: { id: 'FSR', name: 'FidelityFX Super Resolution', style: 'section' }, + type: CCFloat, + range: [0, 1, 0.01], + slide: true, + }) + set fsrSharpness(value: number) { + this._settings.fsr.sharpness = value; + } + get fsrSharpness(): number { + return this._settings.fsr.sharpness; + } + @property({ group: { id: 'ToneMapping', name: 'ToneMapping', style: 'section' }, type: Material, diff --git a/editor/assets/default_renderpipeline/builtin-pipeline-types.ts b/editor/assets/default_renderpipeline/builtin-pipeline-types.ts index 1b90a47f7c9..7440d6588c1 100644 --- a/editor/assets/default_renderpipeline/builtin-pipeline-types.ts +++ b/editor/assets/default_renderpipeline/builtin-pipeline-types.ts @@ -54,6 +54,90 @@ export function fillRequiredMSAA(value: MSAA): void { } } +export interface HBAO { + enabled: boolean; /* false */ + radiusScale: number; /* 1 */ + angleBiasDegree: number; /* 10 */ + blurSharpness: number; /* 3 */ + aoSaturation: number; /* 1 */ + needBlur: boolean; /* false */ + [name: string]: unknown; +} + +export function makeHBAO(): HBAO { + return { + enabled: false, + radiusScale: 1, + angleBiasDegree: 10, + blurSharpness: 3, + aoSaturation: 1, + needBlur: false, + }; +} + +export function fillRequiredHBAO(value: HBAO): void { + if (value.enabled === undefined) { + value.enabled = false; + } + if (value.radiusScale === undefined) { + value.radiusScale = 1; + } + if (value.angleBiasDegree === undefined) { + value.angleBiasDegree = 10; + } + if (value.blurSharpness === undefined) { + value.blurSharpness = 3; + } + if (value.aoSaturation === undefined) { + value.aoSaturation = 1; + } + if (value.needBlur === undefined) { + value.needBlur = false; + } +} + +export interface Bloom { + enabled: boolean; /* false */ + /* refcount */ material: Material | null; + enableAlphaMask: boolean; /* false */ + iterations: number; /* 3 */ + threshold: number; /* 0.8 */ + intensity: number; /* 2.3 */ + [name: string]: unknown; +} + +export function makeBloom(): Bloom { + return { + enabled: false, + material: null, + enableAlphaMask: false, + iterations: 3, + threshold: 0.8, + intensity: 2.3, + }; +} + +export function fillRequiredBloom(value: Bloom): void { + if (value.enabled === undefined) { + value.enabled = false; + } + if (value.material === undefined) { + value.material = null; + } + if (value.enableAlphaMask === undefined) { + value.enableAlphaMask = false; + } + if (value.iterations === undefined) { + value.iterations = 3; + } + if (value.threshold === undefined) { + value.threshold = 0.8; + } + if (value.intensity === undefined) { + value.intensity = 2.3; + } +} + export interface ColorGrading { enabled: boolean; /* false */ /* refcount */ material: Material | null; @@ -86,6 +170,55 @@ export function fillRequiredColorGrading(value: ColorGrading): void { } } +export interface FSR { + enabled: boolean; /* false */ + /* refcount */ material: Material | null; + sharpness: number; /* 0.8 */ + [name: string]: unknown; +} + +export function makeFSR(): FSR { + return { + enabled: false, + material: null, + sharpness: 0.8, + }; +} + +export function fillRequiredFSR(value: FSR): void { + if (value.enabled === undefined) { + value.enabled = false; + } + if (value.material === undefined) { + value.material = null; + } + if (value.sharpness === undefined) { + value.sharpness = 0.8; + } +} + +export interface FXAA { + enabled: boolean; /* false */ + /* refcount */ material: Material | null; + [name: string]: unknown; +} + +export function makeFXAA(): FXAA { + return { + enabled: false, + material: null, + }; +} + +export function fillRequiredFXAA(value: FXAA): void { + if (value.enabled === undefined) { + value.enabled = false; + } + if (value.material === undefined) { + value.material = null; + } +} + export interface ToneMapping { /* refcount */ material: Material | null; [name: string]: unknown; @@ -107,8 +240,11 @@ export interface PipelineSettings { readonly msaa: MSAA; enableShadingScale: boolean; /* false */ shadingScale: number; /* 0.5 */ + readonly bloom: Bloom; readonly toneMapping: ToneMapping; readonly colorGrading: ColorGrading; + readonly fsr: FSR; + readonly fxaa: FXAA; [name: string]: unknown; } @@ -117,8 +253,11 @@ export function makePipelineSettings(): PipelineSettings { msaa: makeMSAA(), enableShadingScale: false, shadingScale: 0.5, + bloom: makeBloom(), toneMapping: makeToneMapping(), colorGrading: makeColorGrading(), + fsr: makeFSR(), + fxaa: makeFXAA(), }; } @@ -134,6 +273,11 @@ export function fillRequiredPipelineSettings(value: PipelineSettings): void { if (value.shadingScale === undefined) { value.shadingScale = 0.5; } + if (!value.bloom) { + (value.bloom as Bloom) = makeBloom(); + } else { + fillRequiredBloom(value.bloom); + } if (!value.toneMapping) { (value.toneMapping as ToneMapping) = makeToneMapping(); } else { @@ -144,4 +288,14 @@ export function fillRequiredPipelineSettings(value: PipelineSettings): void { } else { fillRequiredColorGrading(value.colorGrading); } + if (!value.fsr) { + (value.fsr as FSR) = makeFSR(); + } else { + fillRequiredFSR(value.fsr); + } + if (!value.fxaa) { + (value.fxaa as FXAA) = makeFXAA(); + } else { + fillRequiredFXAA(value.fxaa); + } } diff --git a/editor/assets/default_renderpipeline/builtin-pipeline.ts b/editor/assets/default_renderpipeline/builtin-pipeline.ts index 9533bc1c063..8e18e8ad4bc 100644 --- a/editor/assets/default_renderpipeline/builtin-pipeline.ts +++ b/editor/assets/default_renderpipeline/builtin-pipeline.ts @@ -172,7 +172,7 @@ function sortPipelinePassBuildersByRenderOrder(passBuilders: rendering.PipelineP }); } -export function addCopyToScreenPass( +function addCopyToScreenPass( ppl: rendering.BasicPipeline, pplConfigs: Readonly, cameraConfigs: CameraConfigs, @@ -979,6 +979,181 @@ export class BuiltinForwardPassBuilder implements rendering.PipelinePassBuilder private readonly _reflectionProbeClearColor = new Vec3(0, 0, 0); } +export interface BloomPassConfigs { + enableBloom: boolean; +} + +export class BuiltinBloomPassBuilder implements rendering.PipelinePassBuilder { + getConfigOrder(): number { + return 0; + } + getRenderOrder(): number { + return 200; + } + configCamera( + camera: Readonly, + pipelineConfigs: Readonly, + cameraConfigs: CameraConfigs & BloomPassConfigs): void { + cameraConfigs.enableBloom + = cameraConfigs.settings.bloom.enabled + && !!cameraConfigs.settings.bloom.material; + if (cameraConfigs.enableBloom) { + ++cameraConfigs.remainingPasses; + } + } + windowResize( + ppl: rendering.BasicPipeline, + pplConfigs: Readonly, + cameraConfigs: CameraConfigs & BloomPassConfigs, + window: renderer.RenderWindow): void { + if (cameraConfigs.enableBloom) { + const id = window.renderWindowId; + let bloomWidth = cameraConfigs.width; + let bloomHeight = cameraConfigs.height; + for (let i = 0; i !== cameraConfigs.settings.bloom.iterations + 1; ++i) { + bloomWidth = Math.max(Math.floor(bloomWidth / 2), 1); + bloomHeight = Math.max(Math.floor(bloomHeight / 2), 1); + ppl.addRenderTarget(`BloomTex${id}_${i}`, + cameraConfigs.radianceFormat, bloomWidth, bloomHeight); + } + } + } + + setup( + ppl: rendering.BasicPipeline, + pplConfigs: Readonly, + cameraConfigs: CameraConfigs & BloomPassConfigs, + camera: renderer.scene.Camera, + context: PipelineContext, + prevRenderPass?: rendering.BasicRenderPassBuilder) + : rendering.BasicRenderPassBuilder | undefined { + if (!cameraConfigs.enableBloom) { + return prevRenderPass; + } + + --cameraConfigs.remainingPasses; + assert(cameraConfigs.remainingPasses >= 0); + const id = camera.window.renderWindowId; + assert(!!cameraConfigs.settings.bloom.material); + return this._addKawaseDualFilterBloomPasses( + ppl, pplConfigs, + cameraConfigs, + cameraConfigs.settings, + cameraConfigs.settings.bloom.material, + id, + cameraConfigs.width, + cameraConfigs.height, + context.colorName); + } + + private _addKawaseDualFilterBloomPasses( + ppl: rendering.BasicPipeline, + pplConfigs: Readonly, + cameraConfigs: CameraConfigs & Readonly, + settings: PipelineSettings, + bloomMaterial: Material, + id: number, + width: number, + height: number, + radianceName: string, + ): rendering.BasicRenderPassBuilder { + const QueueHint = rendering.QueueHint; + // Based on Kawase Dual Filter Blur. Saves bandwidth on mobile devices. + // eslint-disable-next-line max-len + // https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_slides.pdf + + // Size: [prefilter(1/2), downsample(1/4), downsample(1/8), downsample(1/16), ...] + const iterations = settings.bloom.iterations; + const sizeCount = iterations + 1; + this._bloomWidths.length = sizeCount; + this._bloomHeights.length = sizeCount; + this._bloomWidths[0] = Math.max(Math.floor(width / 2), 1); + this._bloomHeights[0] = Math.max(Math.floor(height / 2), 1); + for (let i = 1; i !== sizeCount; ++i) { + this._bloomWidths[i] = Math.max(Math.floor(this._bloomWidths[i - 1] / 2), 1); + this._bloomHeights[i] = Math.max(Math.floor(this._bloomHeights[i - 1] / 2), 1); + } + + // Bloom texture names + this._bloomTexNames.length = sizeCount; + for (let i = 0; i !== sizeCount; ++i) { + this._bloomTexNames[i] = `BloomTex${id}_${i}`; + } + + // Setup bloom parameters + this._bloomParams.x = pplConfigs.useFloatOutput ? 1 : 0; + this._bloomParams.x = 0; // unused + this._bloomParams.z = settings.bloom.threshold; + this._bloomParams.w = settings.bloom.enableAlphaMask ? 1 : 0; + + // Prefilter pass + const prefilterPass = ppl.addRenderPass(this._bloomWidths[0], this._bloomHeights[0], 'cc-bloom-prefilter'); + prefilterPass.addRenderTarget( + this._bloomTexNames[0], + LoadOp.CLEAR, + StoreOp.STORE, + this._clearColorTransparentBlack, + ); + prefilterPass.addTexture(radianceName, 'inputTexture'); + prefilterPass.setVec4('g_platform', pplConfigs.platform); + prefilterPass.setVec4('bloomParams', this._bloomParams); + prefilterPass + .addQueue(QueueHint.OPAQUE) + .addFullscreenQuad(bloomMaterial, 0); + + // Downsample passes + for (let i = 1; i !== sizeCount; ++i) { + const downPass = ppl.addRenderPass(this._bloomWidths[i], this._bloomHeights[i], 'cc-bloom-downsample'); + downPass.addRenderTarget(this._bloomTexNames[i], LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); + downPass.addTexture(this._bloomTexNames[i - 1], 'bloomTexture'); + this._bloomTexSize.x = this._bloomWidths[i - 1]; + this._bloomTexSize.y = this._bloomHeights[i - 1]; + downPass.setVec4('g_platform', pplConfigs.platform); + downPass.setVec4('bloomTexSize', this._bloomTexSize); + downPass + .addQueue(QueueHint.OPAQUE) + .addFullscreenQuad(bloomMaterial, 1); + } + + // Upsample passes + for (let i = iterations; i-- > 0;) { + const upPass = ppl.addRenderPass(this._bloomWidths[i], this._bloomHeights[i], 'cc-bloom-upsample'); + upPass.addRenderTarget(this._bloomTexNames[i], LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack); + upPass.addTexture(this._bloomTexNames[i + 1], 'bloomTexture'); + this._bloomTexSize.x = this._bloomWidths[i + 1]; + this._bloomTexSize.y = this._bloomHeights[i + 1]; + upPass.setVec4('g_platform', pplConfigs.platform); + upPass.setVec4('bloomTexSize', this._bloomTexSize); + upPass + .addQueue(QueueHint.OPAQUE) + .addFullscreenQuad(bloomMaterial, 2); + } + + // Combine pass + const combinePass = ppl.addRenderPass(width, height, 'cc-bloom-combine'); + combinePass.addRenderTarget(radianceName, LoadOp.LOAD, StoreOp.STORE); + combinePass.addTexture(this._bloomTexNames[0], 'bloomTexture'); + combinePass.setVec4('g_platform', pplConfigs.platform); + combinePass.setVec4('bloomParams', this._bloomParams); + combinePass + .addQueue(QueueHint.BLEND) + .addFullscreenQuad(bloomMaterial, 3); + + if (cameraConfigs.remainingPasses === 0) { + return addCopyToScreenPass(ppl, pplConfigs, cameraConfigs, radianceName); + } else { + return combinePass; + } + } + // Bloom + private readonly _clearColorTransparentBlack = new Color(0, 0, 0, 0); + private readonly _bloomParams = new Vec4(0, 0, 0, 0); + private readonly _bloomTexSize = new Vec4(0, 0, 0, 0); + private readonly _bloomWidths: Array = []; + private readonly _bloomHeights: Array = []; + private readonly _bloomTexNames: Array = []; +} + export interface ToneMappingPassConfigs { enableToneMapping: boolean; enableColorGrading: boolean; @@ -1037,7 +1212,7 @@ export class BuiltinToneMappingPassBuilder implements rendering.PipelinePassBuil assert(cameraConfigs.remainingPasses >= 0); if (cameraConfigs.remainingPasses === 0) { return this._addCopyAndTonemapPass(ppl, pplConfigs, cameraConfigs, - cameraConfigs.nativeWidth, cameraConfigs.nativeHeight, + cameraConfigs.width, cameraConfigs.height, context.colorName, cameraConfigs.colorName); } else { const id = cameraConfigs.renderWindowId; @@ -1105,6 +1280,214 @@ export class BuiltinToneMappingPassBuilder implements rendering.PipelinePassBuil private readonly _colorGradingTexSize = new Vec2(0, 0); } +export interface FXAAPassConfigs { + enableFXAA: boolean; +} + +export class BuiltinFXAAPassBuilder implements rendering.PipelinePassBuilder { + getConfigOrder(): number { + return 0; + } + getRenderOrder(): number { + return 400; + } + configCamera( + camera: Readonly, + pplConfigs: Readonly, + cameraConfigs: CameraConfigs & FXAAPassConfigs): void { + cameraConfigs.enableFXAA + = cameraConfigs.settings.fxaa.enabled + && !!cameraConfigs.settings.fxaa.material; + if (cameraConfigs.enableFXAA) { + ++cameraConfigs.remainingPasses; + } + } + setup( + ppl: rendering.BasicPipeline, + pplConfigs: Readonly, + cameraConfigs: CameraConfigs & FXAAPassConfigs, + camera: renderer.scene.Camera, + context: PipelineContext, + prevRenderPass?: rendering.BasicRenderPassBuilder) + : rendering.BasicRenderPassBuilder | undefined { + if (!cameraConfigs.enableFXAA) { + return prevRenderPass; + } + --cameraConfigs.remainingPasses; + assert(cameraConfigs.remainingPasses >= 0); + + const id = cameraConfigs.renderWindowId; + const ldrColorPrefix = cameraConfigs.enableShadingScale + ? `ScaledLdrColor` + : `LdrColor`; + const ldrColorName = getPingPongRenderTarget(context.colorName, ldrColorPrefix, id); + + assert(!!cameraConfigs.settings.fxaa.material); + if (cameraConfigs.remainingPasses === 0) { + if (cameraConfigs.enableShadingScale) { + this._addFxaaPass(ppl, pplConfigs, + cameraConfigs.settings.fxaa.material, + cameraConfigs.width, + cameraConfigs.height, + context.colorName, + ldrColorName); + return addCopyToScreenPass(ppl, pplConfigs, cameraConfigs, ldrColorName); + } else { + assert(cameraConfigs.width === cameraConfigs.nativeWidth); + assert(cameraConfigs.height === cameraConfigs.nativeHeight); + return this._addFxaaPass(ppl, pplConfigs, + cameraConfigs.settings.fxaa.material, + cameraConfigs.width, + cameraConfigs.height, + context.colorName, + cameraConfigs.colorName); + } + } else { + const inputColorName = context.colorName; + context.colorName = ldrColorName; + const lastPass = this._addFxaaPass(ppl, pplConfigs, + cameraConfigs.settings.fxaa.material, + cameraConfigs.width, + cameraConfigs.height, + inputColorName, + ldrColorName); + return lastPass; + } + } + private _addFxaaPass( + ppl: rendering.BasicPipeline, + pplConfigs: Readonly, + fxaaMaterial: Material, + width: number, + height: number, + ldrColorName: string, + colorName: string, + ): rendering.BasicRenderPassBuilder { + this._fxaaParams.x = width; + this._fxaaParams.y = height; + this._fxaaParams.z = 1 / width; + this._fxaaParams.w = 1 / height; + + const pass = ppl.addRenderPass(width, height, 'cc-fxaa'); + pass.addRenderTarget(colorName, LoadOp.CLEAR, StoreOp.STORE, sClearColorTransparentBlack); + pass.addTexture(ldrColorName, 'sceneColorMap'); + pass.setVec4('g_platform', pplConfigs.platform); + pass.setVec4('texSize', this._fxaaParams); + pass.addQueue(rendering.QueueHint.OPAQUE) + .addFullscreenQuad(fxaaMaterial, 0); + return pass; + } + // FXAA + private readonly _fxaaParams = new Vec4(0, 0, 0, 0); +} + +export interface FSRPassConfigs { + enableFSR: boolean; +} + +export class BuiltinFsrPassBuilder implements rendering.PipelinePassBuilder { + getConfigOrder(): number { + return 0; + } + getRenderOrder(): number { + return 500; + } + configCamera( + camera: Readonly, + pplConfigs: Readonly, + cameraConfigs: CameraConfigs & FSRPassConfigs): void { + // FSR (Depend on Shading scale) + cameraConfigs.enableFSR = cameraConfigs.settings.fsr.enabled + && !!cameraConfigs.settings.fsr.material + && cameraConfigs.enableShadingScale + && cameraConfigs.shadingScale < 1.0; + + if (cameraConfigs.enableFSR) { + ++cameraConfigs.remainingPasses; + } + } + setup( + ppl: rendering.BasicPipeline, + pplConfigs: Readonly, + cameraConfigs: CameraConfigs & FSRPassConfigs, + camera: renderer.scene.Camera, + context: PipelineContext, + prevRenderPass?: rendering.BasicRenderPassBuilder) + : rendering.BasicRenderPassBuilder | undefined { + if (!cameraConfigs.enableFSR) { + return prevRenderPass; + } + --cameraConfigs.remainingPasses; + + const inputColorName = context.colorName; + const outputColorName + = cameraConfigs.remainingPasses === 0 + ? cameraConfigs.colorName + : getPingPongRenderTarget(context.colorName, 'UiColor', cameraConfigs.renderWindowId); + context.colorName = outputColorName; + + assert(!!cameraConfigs.settings.fsr.material); + return this._addFsrPass(ppl, pplConfigs, cameraConfigs, + cameraConfigs.settings, + cameraConfigs.settings.fsr.material, + cameraConfigs.renderWindowId, + cameraConfigs.width, + cameraConfigs.height, + inputColorName, + cameraConfigs.nativeWidth, + cameraConfigs.nativeHeight, + outputColorName); + } + private _addFsrPass( + ppl: rendering.BasicPipeline, + pplConfigs: Readonly, + cameraConfigs: CameraConfigs & FSRPassConfigs, + settings: PipelineSettings, + fsrMaterial: Material, + id: number, + width: number, + height: number, + inputColorName: string, + nativeWidth: number, + nativeHeight: number, + outputColorName: string, + ): rendering.BasicRenderPassBuilder { + this._fsrTexSize.x = width; + this._fsrTexSize.y = height; + this._fsrTexSize.z = nativeWidth; + this._fsrTexSize.w = nativeHeight; + this._fsrParams.x = clamp(1.0 - settings.fsr.sharpness, 0.02, 0.98); + + const uiColorPrefix = 'UiColor'; + + const fsrColorName = getPingPongRenderTarget(outputColorName, uiColorPrefix, id); + + const easuPass = ppl.addRenderPass(nativeWidth, nativeHeight, 'cc-fsr-easu'); + easuPass.addRenderTarget(fsrColorName, LoadOp.CLEAR, StoreOp.STORE, sClearColorTransparentBlack); + easuPass.addTexture(inputColorName, 'outputResultMap'); + easuPass.setVec4('g_platform', pplConfigs.platform); + easuPass.setVec4('fsrTexSize', this._fsrTexSize); + easuPass + .addQueue(rendering.QueueHint.OPAQUE) + .addFullscreenQuad(fsrMaterial, 0); + + const rcasPass = ppl.addRenderPass(nativeWidth, nativeHeight, 'cc-fsr-rcas'); + rcasPass.addRenderTarget(outputColorName, LoadOp.CLEAR, StoreOp.STORE, sClearColorTransparentBlack); + rcasPass.addTexture(fsrColorName, 'outputResultMap'); + rcasPass.setVec4('g_platform', pplConfigs.platform); + rcasPass.setVec4('fsrTexSize', this._fsrTexSize); + rcasPass.setVec4('fsrParams', this._fsrParams); + rcasPass + .addQueue(rendering.QueueHint.OPAQUE) + .addFullscreenQuad(fsrMaterial, 1); + + return rcasPass; + } + // FSR + private readonly _fsrParams = new Vec4(0, 0, 0, 0); + private readonly _fsrTexSize = new Vec4(0, 0, 0, 0); +} + export class BuiltinUiPassBuilder implements rendering.PipelinePassBuilder { getConfigOrder(): number { return 0; @@ -1115,7 +1498,7 @@ export class BuiltinUiPassBuilder implements rendering.PipelinePassBuilder { setup( ppl: rendering.BasicPipeline, pplConfigs: Readonly, - cameraConfigs: CameraConfigs, + cameraConfigs: CameraConfigs & FSRPassConfigs, camera: renderer.scene.Camera, context: PipelineContext, prevRenderPass?: rendering.BasicRenderPassBuilder) @@ -1142,7 +1525,10 @@ if (rendering) { class BuiltinPipelineBuilder implements rendering.PipelineBuilder { private readonly _pipelineEvent: PipelineEventProcessor = cclegacy.director.root.pipelineEvent as PipelineEventProcessor; private readonly _forwardPass = new BuiltinForwardPassBuilder(); + private readonly _bloomPass = new BuiltinBloomPassBuilder(); private readonly _toneMappingPass = new BuiltinToneMappingPassBuilder(); + private readonly _fxaaPass = new BuiltinFXAAPassBuilder(); + private readonly _fsrPass = new BuiltinFsrPassBuilder(); private readonly _uiPass = new BuiltinUiPassBuilder(); // Internal cached resources private readonly _clearColor = new Color(0, 0, 0, 1); @@ -1192,7 +1578,20 @@ if (rendering) { } passBuilders.push(this._forwardPass); + + if (settings.bloom.enabled) { + passBuilders.push(this._bloomPass); + } + passBuilders.push(this._toneMappingPass); + + if (settings.fxaa.enabled) { + passBuilders.push(this._fxaaPass); + } + + if (settings.fsr.enabled) { + passBuilders.push(this._fsrPass); + } passBuilders.push(this._uiPass); }