diff --git a/editor/assets/default_renderpipeline/builtin-bloom-pass.ts b/editor/assets/default_renderpipeline/builtin-bloom-pass.ts new file mode 100644 index 00000000000..c93e5c26a29 --- /dev/null +++ b/editor/assets/default_renderpipeline/builtin-bloom-pass.ts @@ -0,0 +1,326 @@ +/* + 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 new file mode 100644 index 00000000000..b3d30c396a9 --- /dev/null +++ b/editor/assets/default_renderpipeline/builtin-bloom-pass.ts.meta @@ -0,0 +1,9 @@ +{ + "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 11a6ab56f42..97fa7d451f8 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 - private _enableDof = false; + protected _enableDof = false; @property - private _material: Material | null = null; + protected _material: Material | null = null; @property - private _minRange = 0; + protected _minRange = 0; @property - private _maxRange = 2; + protected _maxRange = 2; @property - private _blurRadius = 1; + protected _blurRadius = 1; @property - private _intensity = 1; + protected _intensity = 1; @property - private _focusPos = new Vec3(0, 0, 0); + protected _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 new file mode 100644 index 00000000000..c670664dc6a --- /dev/null +++ b/editor/assets/default_renderpipeline/builtin-fsr-pass.ts @@ -0,0 +1,218 @@ +/* + 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 new file mode 100644 index 00000000000..e7557ab6c13 --- /dev/null +++ b/editor/assets/default_renderpipeline/builtin-fsr-pass.ts.meta @@ -0,0 +1,9 @@ +{ + "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 new file mode 100644 index 00000000000..d3a4b19693f --- /dev/null +++ b/editor/assets/default_renderpipeline/builtin-fxaa-pass.ts @@ -0,0 +1,198 @@ +/* + 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 new file mode 100644 index 00000000000..29ad07f79e3 --- /dev/null +++ b/editor/assets/default_renderpipeline/builtin-fxaa-pass.ts.meta @@ -0,0 +1,9 @@ +{ + "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 c4bc43f9990..a8d82d3063f 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, type } = _decorator; +const { ccclass, disallowMultiple, executeInEditMode, menu, property, requireComponent } = _decorator; @ccclass('BuiltinPipelineSettings') @menu('Rendering/BuiltinPipelineSettings') @@ -170,90 +170,6 @@ 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' }, @@ -315,83 +231,6 @@ 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 7440d6588c1..1b90a47f7c9 100644 --- a/editor/assets/default_renderpipeline/builtin-pipeline-types.ts +++ b/editor/assets/default_renderpipeline/builtin-pipeline-types.ts @@ -54,90 +54,6 @@ 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; @@ -170,55 +86,6 @@ 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; @@ -240,11 +107,8 @@ 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; } @@ -253,11 +117,8 @@ export function makePipelineSettings(): PipelineSettings { msaa: makeMSAA(), enableShadingScale: false, shadingScale: 0.5, - bloom: makeBloom(), toneMapping: makeToneMapping(), colorGrading: makeColorGrading(), - fsr: makeFSR(), - fxaa: makeFXAA(), }; } @@ -273,11 +134,6 @@ 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 { @@ -288,14 +144,4 @@ 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 d12d4ced141..249bdcccc20 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 }); } -function addCopyToScreenPass( +export function addCopyToScreenPass( ppl: rendering.BasicPipeline, pplConfigs: Readonly, cameraConfigs: CameraConfigs, @@ -978,181 +978,6 @@ 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; @@ -1211,7 +1036,7 @@ export class BuiltinToneMappingPassBuilder implements rendering.PipelinePassBuil assert(cameraConfigs.remainingPasses >= 0); if (cameraConfigs.remainingPasses === 0) { return this._addCopyAndTonemapPass(ppl, pplConfigs, cameraConfigs, - cameraConfigs.width, cameraConfigs.height, + cameraConfigs.nativeWidth, cameraConfigs.nativeHeight, context.colorName, cameraConfigs.colorName); } else { const id = cameraConfigs.renderWindowId; @@ -1279,214 +1104,6 @@ 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; @@ -1497,7 +1114,7 @@ export class BuiltinUiPassBuilder implements rendering.PipelinePassBuilder { setup( ppl: rendering.BasicPipeline, pplConfigs: Readonly, - cameraConfigs: CameraConfigs & FSRPassConfigs, + cameraConfigs: CameraConfigs, camera: renderer.scene.Camera, context: PipelineContext, prevRenderPass?: rendering.BasicRenderPassBuilder) @@ -1524,10 +1141,7 @@ 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); @@ -1577,20 +1191,7 @@ 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); }