From ac6003147329dad5c007d11bd17acf78389ca2b8 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Fri, 5 Sep 2025 17:49:49 +0800 Subject: [PATCH 01/35] refactor: opt scene --- packages/core/src/Scene.ts | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/packages/core/src/Scene.ts b/packages/core/src/Scene.ts index ed83d18839..5e3f6d9aa7 100644 --- a/packages/core/src/Scene.ts +++ b/packages/core/src/Scene.ts @@ -53,6 +53,14 @@ export class Scene extends EngineObject { /** Post process manager. */ readonly postProcessManager = new PostProcessManager(this); + /** + * Screen Space Ambient Occlusion (SSAO) settings. + * @remarks + * Darkens areas where objects are close together to simulate natural light blocking, + * such as corners, crevices, and contact points between surfaces. + */ + readonly ssao = new ScreenSpaceAmbientOcclusion(); + /* @internal */ _lightManager: LightManager = new LightManager(); /* @internal */ @@ -79,7 +87,6 @@ export class Scene extends EngineObject { private _isActive: boolean = true; private _sun: DirectLight | null; private _enableTransparentShadow = false; - private _ssao = new ScreenSpaceAmbientOcclusion(); /** * Whether the scene is active. @@ -266,22 +273,6 @@ export class Scene extends EngineObject { } } - /** - * Screen Space Ambient Occlusion (SSAO) settings. - * @remarks - * Darkens areas where objects are close together to simulate natural light blocking, - * such as corners, crevices, and contact points between surfaces. - */ - get ssao(): ScreenSpaceAmbientOcclusion { - return this._ssao; - } - - set ssao(value: ScreenSpaceAmbientOcclusion) { - if (this._ssao !== value) { - this._ssao = value; - } - } - /** * Create scene. * @param engine - Engine From 6efca03e8b4ae935733f50b3a4d90f724a66e72b Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Fri, 5 Sep 2025 18:02:47 +0800 Subject: [PATCH 02/35] refactor: opt code --- packages/core/src/shaderlib/common.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/shaderlib/common.glsl b/packages/core/src/shaderlib/common.glsl index 1fc89a57ef..a4b7075836 100644 --- a/packages/core/src/shaderlib/common.glsl +++ b/packages/core/src/shaderlib/common.glsl @@ -82,7 +82,7 @@ float remapDepthBufferLinear01(float z){ return 1.0/ (camera_DepthBufferParams.x * z + camera_DepthBufferParams.y); } -//From Next Generation Post Processing in Call of Duty: Advanced Warfare [Jimenez 2014] +// From Next Generation Post Processing in Call of Duty: Advanced Warfare [Jimenez 2014] // http://advances.realtimerendering.com/s2014/index.html float interleavedGradientNoise(vec2 pixCoord) { From fe7fab83be43d2653179dbd05767a668f2339125 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Fri, 5 Sep 2025 23:05:56 +0800 Subject: [PATCH 03/35] refactor: opt code --- packages/core/src/lighting/enums/SSAOQuality.ts | 11 +++++++++++ ...sionEffect.ts => ScreenSpaceAmbientOcclusion.ts} | 13 ++----------- .../ScreenSpaceAmbientOcclusionPass.ts | 3 ++- .../core/src/lighting/screenSpaceLighting/index.ts | 4 +++- 4 files changed, 18 insertions(+), 13 deletions(-) create mode 100644 packages/core/src/lighting/enums/SSAOQuality.ts rename packages/core/src/lighting/screenSpaceLighting/{ScreenSpaceAmbientOcclusionEffect.ts => ScreenSpaceAmbientOcclusion.ts} (94%) diff --git a/packages/core/src/lighting/enums/SSAOQuality.ts b/packages/core/src/lighting/enums/SSAOQuality.ts new file mode 100644 index 0000000000..5b589bd904 --- /dev/null +++ b/packages/core/src/lighting/enums/SSAOQuality.ts @@ -0,0 +1,11 @@ +/** + * Screen Space Ambient Occlusion quality levels. + */ +export enum SSAOQuality { + /** Low quality - fewer samples, faster performance */ + Low = 0, + /** Medium quality - balanced samples and performance */ + Medium = 1, + /** High quality - more samples, better quality */ + High = 2 +} \ No newline at end of file diff --git a/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionEffect.ts b/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts similarity index 94% rename from packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionEffect.ts rename to packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts index 55cc01ab80..f18d9c0c52 100644 --- a/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionEffect.ts +++ b/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts @@ -2,18 +2,9 @@ import { Shader, ShaderMacro, ShaderPass, ShaderProperty } from "../../shader"; import blitVs from "../../shaderlib/extra/Blit.vs.glsl"; import scalableAmbientOcclusionFS from "./shaders/ScalableAmbientOcclusion.glsl"; import bilateralBlurFS from "./shaders/Blur/BilateralBlur.glsl"; +import { SSAOQuality } from "../enums/SSAOQuality"; + -/** - * Screen Space Ambient Occlusion quality levels. - */ -export enum SSAOQuality { - /** Low quality - fewer samples, faster performance */ - Low = 0, - /** Medium quality - balanced samples and performance */ - Medium = 1, - /** High quality - more samples, better quality */ - High = 2 -} /** * Screen Space Ambient Occlusion effect configuration. diff --git a/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionPass.ts b/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionPass.ts index c578367499..ad75d2ce9a 100644 --- a/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionPass.ts +++ b/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionPass.ts @@ -7,9 +7,10 @@ import { Blitter } from "../../RenderPipeline/Blitter"; import { PipelinePass } from "../../RenderPipeline/PipelinePass"; import { PipelineUtils } from "../../RenderPipeline/PipelineUtils"; import { RenderContext } from "../../RenderPipeline/RenderContext"; -import { ScreenSpaceAmbientOcclusion, SSAOQuality } from "./ScreenSpaceAmbientOcclusionEffect"; import { Vector2, Vector4 } from "@galacean/engine-math"; import { SystemInfo } from "../../SystemInfo"; +import { SSAOQuality } from "../enums/SSAOQuality"; +import { ScreenSpaceAmbientOcclusion } from "./ScreenSpaceAmbientOcclusion"; /** * @internal diff --git a/packages/core/src/lighting/screenSpaceLighting/index.ts b/packages/core/src/lighting/screenSpaceLighting/index.ts index e68d3a9d13..2c8bc6875a 100644 --- a/packages/core/src/lighting/screenSpaceLighting/index.ts +++ b/packages/core/src/lighting/screenSpaceLighting/index.ts @@ -1 +1,3 @@ -export { ScreenSpaceAmbientOcclusion, SSAOQuality } from "./ScreenSpaceAmbientOcclusionEffect"; +export { SSAOQuality } from "../enums/SSAOQuality"; +export { ScreenSpaceAmbientOcclusion } from "./ScreenSpaceAmbientOcclusion"; + From 6677cbd64856cf16819e4425cc11e809127dfb6e Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Fri, 5 Sep 2025 23:39:26 +0800 Subject: [PATCH 04/35] refactor: opt param names --- packages/core/src/shaderlib/common.glsl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/core/src/shaderlib/common.glsl b/packages/core/src/shaderlib/common.glsl index a4b7075836..26edb214ca 100644 --- a/packages/core/src/shaderlib/common.glsl +++ b/packages/core/src/shaderlib/common.glsl @@ -84,10 +84,11 @@ float remapDepthBufferLinear01(float z){ // From Next Generation Post Processing in Call of Duty: Advanced Warfare [Jimenez 2014] // http://advances.realtimerendering.com/s2014/index.html -float interleavedGradientNoise(vec2 pixCoord) +// sampleCoord must not be normalized (e.g. window coordinates) +float interleavedGradientNoise(vec2 sampleCoord) { const vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189); - return fract(magic.z * fract(dot(pixCoord, magic.xy))); + return fract(magic.z * fract(dot(sampleCoord, magic.xy))); } #ifdef GRAPHICS_API_WEBGL2 From c0e7bd43e87fbb46eb6f0fc812fb3523ecb64c7b Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 00:24:52 +0800 Subject: [PATCH 05/35] refactor: opt code --- packages/core/src/shaderlib/pbr/pbr_helper.glsl | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index a640810c9e..0c6e7026b5 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -173,18 +173,15 @@ void initMaterial(out Material material, inout Geometry geometry){ diffuseAO = ((texture2D(material_OcclusionTexture, aoUV)).r - 1.0) * material_OcclusionIntensity + 1.0; #endif - #if defined(MATERIAL_HAS_OCCLUSION_TEXTURE) && defined(SCENE_USE_SPECULAR_ENV) - specularAO = saturate( pow( geometry.dotNV + diffuseAO, exp2( - 16.0 * material.roughness - 1.0 ) ) - 1.0 + diffuseAO ); - #endif - - #ifdef SCENE_ENABLE_SSAO + #ifdef SCENE_ENABLE_SSAO vec4 samplingPositionNDC = camera_ProjMat * camera_ViewMat * vec4( geometry.position, 1.0 ); vec2 ssaoUV = (samplingPositionNDC.xy / samplingPositionNDC.w) * 0.5 + 0.5; float ssao = texture2D(camera_SSAOTexture, ssaoUV).r; diffuseAO *= ssao; - #ifdef SCENE_USE_SPECULAR_ENV - specularAO = saturate(pow( geometry.dotNV + diffuseAO, exp2(-16.0 * material.roughness - 1.0)) - 1.0 + diffuseAO); - #endif + #endif + + #if (defined(MATERIAL_HAS_OCCLUSION_TEXTURE) || defined(SCENE_ENABLE_SSAO))&& defined(SCENE_USE_SPECULAR_ENV) + specularAO = saturate( pow( geometry.dotNV + diffuseAO, exp2( - 16.0 * material.roughness - 1.0 ) ) - 1.0 + diffuseAO ); #endif material.diffuseAO = diffuseAO; From c5c58d59ae1cc42fc9c66771ce117ba760823286 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 00:41:29 +0800 Subject: [PATCH 06/35] fix: lint error --- packages/core/src/lighting/enums/SSAOQuality.ts | 2 +- .../lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts | 2 -- packages/core/src/lighting/screenSpaceLighting/index.ts | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/core/src/lighting/enums/SSAOQuality.ts b/packages/core/src/lighting/enums/SSAOQuality.ts index 5b589bd904..0f83cade77 100644 --- a/packages/core/src/lighting/enums/SSAOQuality.ts +++ b/packages/core/src/lighting/enums/SSAOQuality.ts @@ -8,4 +8,4 @@ export enum SSAOQuality { Medium = 1, /** High quality - more samples, better quality */ High = 2 -} \ No newline at end of file +} diff --git a/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts b/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts index f18d9c0c52..2a94e16f47 100644 --- a/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts +++ b/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts @@ -4,8 +4,6 @@ import scalableAmbientOcclusionFS from "./shaders/ScalableAmbientOcclusion.glsl" import bilateralBlurFS from "./shaders/Blur/BilateralBlur.glsl"; import { SSAOQuality } from "../enums/SSAOQuality"; - - /** * Screen Space Ambient Occlusion effect configuration. */ diff --git a/packages/core/src/lighting/screenSpaceLighting/index.ts b/packages/core/src/lighting/screenSpaceLighting/index.ts index 2c8bc6875a..39a7309d3b 100644 --- a/packages/core/src/lighting/screenSpaceLighting/index.ts +++ b/packages/core/src/lighting/screenSpaceLighting/index.ts @@ -1,3 +1,2 @@ export { SSAOQuality } from "../enums/SSAOQuality"; export { ScreenSpaceAmbientOcclusion } from "./ScreenSpaceAmbientOcclusion"; - From 511352c892b417baa0d8e146a116bbc1d92c5651 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 01:07:49 +0800 Subject: [PATCH 07/35] refactor: opt code --- packages/core/src/RenderPipeline/PipelineUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/RenderPipeline/PipelineUtils.ts b/packages/core/src/RenderPipeline/PipelineUtils.ts index e089c43290..50cc808eb3 100644 --- a/packages/core/src/RenderPipeline/PipelineUtils.ts +++ b/packages/core/src/RenderPipeline/PipelineUtils.ts @@ -86,7 +86,7 @@ export class PipelineUtils { ): RenderTarget { const currentColorTexture = currentRenderTarget?.getColorTexture(0); const colorTexture = - colorFormat != undefined + colorFormat != null ? PipelineUtils.recreateTextureIfNeeded( engine, currentColorTexture, From a23b8d92511139b6e20b68e22e5b7b7e99876236 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 01:25:15 +0800 Subject: [PATCH 08/35] refactor: opt code --- e2e/case/camera-ssao.ts | 22 ++++---- .../src/RenderPipeline/BasicRenderPipeline.ts | 6 +-- packages/core/src/Scene.ts | 6 +-- .../AmbientOcclusion.ts} | 12 ++--- .../ScreenSpaceAmbientOcclusionPass.ts | 54 +++++++++---------- .../src/lighting/ambientOcclusion/index.ts | 2 + .../shaders/Blur/BilateralBlur.glsl | 0 .../shaders/ScalableAmbientOcclusion.glsl | 0 ...OQuality.ts => AmbientOcclusionQuality.ts} | 4 +- packages/core/src/lighting/index.ts | 2 +- .../src/lighting/screenSpaceLighting/index.ts | 2 - 11 files changed, 56 insertions(+), 54 deletions(-) rename packages/core/src/lighting/{screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts => ambientOcclusion/AmbientOcclusion.ts} (93%) rename packages/core/src/lighting/{screenSpaceLighting => ambientOcclusion}/ScreenSpaceAmbientOcclusionPass.ts (78%) create mode 100644 packages/core/src/lighting/ambientOcclusion/index.ts rename packages/core/src/lighting/{screenSpaceLighting => ambientOcclusion}/shaders/Blur/BilateralBlur.glsl (100%) rename packages/core/src/lighting/{screenSpaceLighting => ambientOcclusion}/shaders/ScalableAmbientOcclusion.glsl (100%) rename packages/core/src/lighting/enums/{SSAOQuality.ts => AmbientOcclusionQuality.ts} (73%) delete mode 100644 packages/core/src/lighting/screenSpaceLighting/index.ts diff --git a/e2e/case/camera-ssao.ts b/e2e/case/camera-ssao.ts index 15a80d23c7..d0bc20dbb7 100644 --- a/e2e/case/camera-ssao.ts +++ b/e2e/case/camera-ssao.ts @@ -14,14 +14,15 @@ import { PBRMaterial, PrimitiveMesh, SkyBoxMaterial, - SSAOQuality, + AmbientOcclusionQuality, Vector3, - WebGLEngine + WebGLEngine, + WebGLMode } from "@galacean/engine"; import { initScreenshot, updateForE2E } from "./.mockForE2E"; Logger.enable(); -WebGLEngine.create({ canvas: "canvas" }).then((engine) => { +WebGLEngine.create({ canvas: "canvas",graphicDeviceOptions: { webGLMode: WebGLMode.WebGL1 } }).then((engine) => { engine.canvas.resizeByClientSize(2); const scene = engine.sceneManager.activeScene; const rootEntity = scene.createRootEntity(); @@ -32,13 +33,13 @@ WebGLEngine.create({ canvas: "canvas" }).then((engine) => { cameraEntity.transform.position = new Vector3(0.8, 1, 3.5); const camera = cameraEntity.addComponent(Camera); - scene.ssao.enabled = true; - scene.ssao.radius = 0.4; - scene.ssao.intensity = 3; - scene.ssao.power = 1.0; - scene.ssao.bias = 0.0005; - scene.ssao.bilateralThreshold = 0.01; - scene.ssao.quality = SSAOQuality.High; + scene.ambientOcclusion.enabled = true; + scene.ambientOcclusion.radius = 0.4; + scene.ambientOcclusion.intensity = 3; + scene.ambientOcclusion.power = 1.0; + scene.ambientOcclusion.bias = 0.0005; + scene.ambientOcclusion.bilateralThreshold = 0.01; + scene.ambientOcclusion.quality = AmbientOcclusionQuality.High; const lightNode = rootEntity.createChild("light_node"); lightNode.addComponent(DirectLight).color = new Color(1, 1, 1); @@ -82,6 +83,7 @@ WebGLEngine.create({ canvas: "canvas" }).then((engine) => { ambientLight.specularIntensity = 1; }) .then(() => { + // engine.run(); updateForE2E(engine); initScreenshot(engine, camera); }); diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index 07a4720a36..6ea0a90caa 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -28,8 +28,8 @@ import { DepthOnlyPass } from "./DepthOnlyPass"; import { OpaqueTexturePass } from "./OpaqueTexturePass"; import { PipelineUtils } from "./PipelineUtils"; import { ContextRendererUpdateFlag, RenderContext } from "./RenderContext"; -import { SSAOPass } from "../lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionPass"; -import { ScreenSpaceAmbientOcclusion } from "../lighting/screenSpaceLighting"; +import { SSAOPass } from "../lighting/ambientOcclusion/ScreenSpaceAmbientOcclusionPass"; +import { AmbientOcclusion } from "../lighting/ambientOcclusion"; import { RenderElement } from "./RenderElement"; import { SubRenderElement } from "./SubRenderElement"; import { PipelineStage } from "./enums/PipelineStage"; @@ -267,7 +267,7 @@ export class BasicRenderPipeline { // Screen space ambient occlusion pass // Before opaque pass so materials can sample ambient occlusion in BRDF - if (scene.ssao.enabled) { + if (scene.ambientOcclusion.enabled) { camera.depthTextureMode = DepthTextureMode.PrePass; const ssaoPass = this._ssaoPass; ssaoPass.onConfig(camera, colorTarget); diff --git a/packages/core/src/Scene.ts b/packages/core/src/Scene.ts index 5e3f6d9aa7..4213c71268 100644 --- a/packages/core/src/Scene.ts +++ b/packages/core/src/Scene.ts @@ -8,7 +8,7 @@ import { SceneManager } from "./SceneManager"; import { EngineObject, Logger } from "./base"; import { ActiveChangeFlag } from "./enums/ActiveChangeFlag"; import { FogMode } from "./enums/FogMode"; -import { DirectLight, ScreenSpaceAmbientOcclusion } from "./lighting"; +import { DirectLight, AmbientOcclusion } from "./lighting"; import { AmbientLight } from "./lighting/AmbientLight"; import { LightManager } from "./lighting/LightManager"; import { PhysicsScene } from "./physics/PhysicsScene"; @@ -54,12 +54,12 @@ export class Scene extends EngineObject { readonly postProcessManager = new PostProcessManager(this); /** - * Screen Space Ambient Occlusion (SSAO) settings. + * Ambient Occlusion settings. * @remarks * Darkens areas where objects are close together to simulate natural light blocking, * such as corners, crevices, and contact points between surfaces. */ - readonly ssao = new ScreenSpaceAmbientOcclusion(); + readonly ambientOcclusion = new AmbientOcclusion(); /* @internal */ _lightManager: LightManager = new LightManager(); diff --git a/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts similarity index 93% rename from packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts rename to packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts index 2a94e16f47..34b821d6fa 100644 --- a/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusion.ts +++ b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts @@ -2,12 +2,12 @@ import { Shader, ShaderMacro, ShaderPass, ShaderProperty } from "../../shader"; import blitVs from "../../shaderlib/extra/Blit.vs.glsl"; import scalableAmbientOcclusionFS from "./shaders/ScalableAmbientOcclusion.glsl"; import bilateralBlurFS from "./shaders/Blur/BilateralBlur.glsl"; -import { SSAOQuality } from "../enums/SSAOQuality"; +import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; /** * Screen Space Ambient Occlusion effect configuration. */ -export class ScreenSpaceAmbientOcclusion { +export class AmbientOcclusion { static readonly SHADER_NAME = "ScalableAmbientOcclusion"; // Shader properties for ambient occlusion calculation @@ -39,7 +39,7 @@ export class ScreenSpaceAmbientOcclusion { static _enableMacro = ShaderMacro.getByName("SCENE_ENABLE_SSAO"); private _enabled: boolean = false; - private _quality: SSAOQuality = SSAOQuality.Low; + private _quality: AmbientOcclusionQuality = AmbientOcclusionQuality.Low; private _radius: number = 0.5; private _intensity: number = 1.0; private _bias: number = 0.01; @@ -67,11 +67,11 @@ export class ScreenSpaceAmbientOcclusion { * If set to `SSAOQuality.Medium`, the effect will balance quality and performance. * If set to `SSAOQuality.High`, the effect will use more samples for better quality,but the performance will be even worse. */ - get quality(): SSAOQuality { + get quality(): AmbientOcclusionQuality { return this._quality; } - set quality(value: SSAOQuality) { + set quality(value: AmbientOcclusionQuality) { if (this._quality !== value) { this._quality = value; } @@ -161,7 +161,7 @@ export class ScreenSpaceAmbientOcclusion { } } -Shader.create(ScreenSpaceAmbientOcclusion.SHADER_NAME, [ +Shader.create(AmbientOcclusion.SHADER_NAME, [ new ShaderPass("ScalableAmbientOcclusion", blitVs, scalableAmbientOcclusionFS), new ShaderPass("BilateralBlur", blitVs, bilateralBlurFS) ]); diff --git a/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionPass.ts b/packages/core/src/lighting/ambientOcclusion/ScreenSpaceAmbientOcclusionPass.ts similarity index 78% rename from packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionPass.ts rename to packages/core/src/lighting/ambientOcclusion/ScreenSpaceAmbientOcclusionPass.ts index ad75d2ce9a..0012eaa9ec 100644 --- a/packages/core/src/lighting/screenSpaceLighting/ScreenSpaceAmbientOcclusionPass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScreenSpaceAmbientOcclusionPass.ts @@ -9,8 +9,8 @@ import { PipelineUtils } from "../../RenderPipeline/PipelineUtils"; import { RenderContext } from "../../RenderPipeline/RenderContext"; import { Vector2, Vector4 } from "@galacean/engine-math"; import { SystemInfo } from "../../SystemInfo"; -import { SSAOQuality } from "../enums/SSAOQuality"; -import { ScreenSpaceAmbientOcclusion } from "./ScreenSpaceAmbientOcclusion"; +import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; +import { AmbientOcclusion } from "./AmbientOcclusion"; /** * @internal @@ -29,19 +29,19 @@ export class SSAOPass extends PipelinePass { private _offsetX = new Vector4(); private _offsetY = new Vector4(); - private _quality: SSAOQuality = SSAOQuality.Low; + private _quality: AmbientOcclusionQuality = AmbientOcclusionQuality.Low; private _kernel: Float32Array = null; constructor(engine: Engine) { super(engine); // Create SSAO material - const ssaoMaterial = new Material(engine, Shader.find(ScreenSpaceAmbientOcclusion.SHADER_NAME)); + const ssaoMaterial = new Material(engine, Shader.find(AmbientOcclusion.SHADER_NAME)); ssaoMaterial._addReferCount(1); this._ssaoMaterial = ssaoMaterial; //Bilateral Blur material - const bilateralBlurMaterial = new Material(engine, Shader.find(ScreenSpaceAmbientOcclusion.SHADER_NAME)); + const bilateralBlurMaterial = new Material(engine, Shader.find(AmbientOcclusion.SHADER_NAME)); bilateralBlurMaterial._addReferCount(1); this._bilateralBlurMaterial = bilateralBlurMaterial; @@ -52,13 +52,13 @@ export class SSAOPass extends PipelinePass { const defaultPower = 1.0; const peak = 0.1 * radius; const intensity = (2 * Math.PI * peak) / this._sampleCount; - ssaoShaderData.setFloat(ScreenSpaceAmbientOcclusion._invRadiusSquaredProp, 1.0 / (radius * radius)); - ssaoShaderData.setFloat(ScreenSpaceAmbientOcclusion._intensityProp, intensity); - ssaoShaderData.setFloat(ScreenSpaceAmbientOcclusion._powerProp, defaultPower * 2.0); - ssaoShaderData.setFloat(ScreenSpaceAmbientOcclusion._peak2Prop, peak * peak); + ssaoShaderData.setFloat(AmbientOcclusion._invRadiusSquaredProp, 1.0 / (radius * radius)); + ssaoShaderData.setFloat(AmbientOcclusion._intensityProp, intensity); + ssaoShaderData.setFloat(AmbientOcclusion._powerProp, defaultPower * 2.0); + ssaoShaderData.setFloat(AmbientOcclusion._peak2Prop, peak * peak); } - private _setQuality(blurShaderData: ShaderData, quality: SSAOQuality): void { + private _setQuality(blurShaderData: ShaderData, quality: AmbientOcclusionQuality): void { if (quality === this._quality && this._kernel !== null) { return; } @@ -67,15 +67,15 @@ export class SSAOPass extends PipelinePass { let standardDeviation: number; switch (quality) { - case SSAOQuality.Low: + case AmbientOcclusionQuality.Low: sampleCount = 7; standardDeviation = 8.0; break; - case SSAOQuality.Medium: + case AmbientOcclusionQuality.Medium: sampleCount = 11; standardDeviation = 8.0; break; - case SSAOQuality.High: + case AmbientOcclusionQuality.High: default: sampleCount = 16; standardDeviation = 6.0; @@ -92,7 +92,7 @@ export class SSAOPass extends PipelinePass { for (let i = sampleCount; i < kernelArraySize; i++) gaussianKernel[i] = 0.0; this._quality = quality; this._kernel = gaussianKernel; - blurShaderData.setFloatArray(ScreenSpaceAmbientOcclusion._kernelProp, gaussianKernel); + blurShaderData.setFloatArray(AmbientOcclusion._kernelProp, gaussianKernel); } onConfig(camera: Camera, inputRenderTarget: RenderTarget): void { @@ -139,7 +139,7 @@ export class SSAOPass extends PipelinePass { const { camera } = context; const { viewport } = camera; const scene = camera.scene; - const ssaoEffect = scene.ssao; + const ssaoEffect = scene.ambientOcclusion; const ssaoShaderData = this._ssaoMaterial.shaderData; const blurShaderData = this._bilateralBlurMaterial.shaderData; const projectionMatrix = context.projectionMatrix; @@ -154,7 +154,7 @@ export class SSAOPass extends PipelinePass { const invProjection1 = 1.0 / projectionMatrix.elements[5]; // 1 / projection[1][1] const position = this._position.set(invProjection0 * 2.0, invProjection1 * 2.0); - ssaoShaderData.setVector2(ScreenSpaceAmbientOcclusion._invPositionProp, position); + ssaoShaderData.setVector2(AmbientOcclusion._invPositionProp, position); if (ssaoEffect?.isValid()) { this._setQuality(blurShaderData, ssaoEffect.quality); @@ -173,20 +173,20 @@ export class SSAOPass extends PipelinePass { const invRadiusSquared = 1.0 / (radius * radius); const farPlaneOverEdgeDistance = -camera.farClipPlane / ssaoEffect.bilateralThreshold; - ssaoShaderData.setFloat(ScreenSpaceAmbientOcclusion._invRadiusSquaredProp, invRadiusSquared); - ssaoShaderData.setFloat(ScreenSpaceAmbientOcclusion._intensityProp, intensity); - ssaoShaderData.setFloat(ScreenSpaceAmbientOcclusion._powerProp, power); - ssaoShaderData.setFloat(ScreenSpaceAmbientOcclusion._projectionScaleRadiusProp, projectionScaleRadius); - ssaoShaderData.setFloat(ScreenSpaceAmbientOcclusion._biasProp, bias); - ssaoShaderData.setFloat(ScreenSpaceAmbientOcclusion._peak2Prop, peak2); - ssaoShaderData.enableMacro(ScreenSpaceAmbientOcclusion._enableMacro); + ssaoShaderData.setFloat(AmbientOcclusion._invRadiusSquaredProp, invRadiusSquared); + ssaoShaderData.setFloat(AmbientOcclusion._intensityProp, intensity); + ssaoShaderData.setFloat(AmbientOcclusion._powerProp, power); + ssaoShaderData.setFloat(AmbientOcclusion._projectionScaleRadiusProp, projectionScaleRadius); + ssaoShaderData.setFloat(AmbientOcclusion._biasProp, bias); + ssaoShaderData.setFloat(AmbientOcclusion._peak2Prop, peak2); + ssaoShaderData.enableMacro(AmbientOcclusion._enableMacro); - blurShaderData.enableMacro(ScreenSpaceAmbientOcclusion._enableMacro); - blurShaderData.setFloat(ScreenSpaceAmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); + blurShaderData.enableMacro(AmbientOcclusion._enableMacro); + blurShaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); } else { scene.shaderData.disableMacro("SCENE_ENABLE_SSAO"); - ssaoShaderData.disableMacro(ScreenSpaceAmbientOcclusion._enableMacro); - blurShaderData.disableMacro(ScreenSpaceAmbientOcclusion._enableMacro); + ssaoShaderData.disableMacro(AmbientOcclusion._enableMacro); + blurShaderData.disableMacro(AmbientOcclusion._enableMacro); return; } diff --git a/packages/core/src/lighting/ambientOcclusion/index.ts b/packages/core/src/lighting/ambientOcclusion/index.ts new file mode 100644 index 0000000000..cfb01397c2 --- /dev/null +++ b/packages/core/src/lighting/ambientOcclusion/index.ts @@ -0,0 +1,2 @@ +export { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; +export { AmbientOcclusion } from "./AmbientOcclusion"; diff --git a/packages/core/src/lighting/screenSpaceLighting/shaders/Blur/BilateralBlur.glsl b/packages/core/src/lighting/ambientOcclusion/shaders/Blur/BilateralBlur.glsl similarity index 100% rename from packages/core/src/lighting/screenSpaceLighting/shaders/Blur/BilateralBlur.glsl rename to packages/core/src/lighting/ambientOcclusion/shaders/Blur/BilateralBlur.glsl diff --git a/packages/core/src/lighting/screenSpaceLighting/shaders/ScalableAmbientOcclusion.glsl b/packages/core/src/lighting/ambientOcclusion/shaders/ScalableAmbientOcclusion.glsl similarity index 100% rename from packages/core/src/lighting/screenSpaceLighting/shaders/ScalableAmbientOcclusion.glsl rename to packages/core/src/lighting/ambientOcclusion/shaders/ScalableAmbientOcclusion.glsl diff --git a/packages/core/src/lighting/enums/SSAOQuality.ts b/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts similarity index 73% rename from packages/core/src/lighting/enums/SSAOQuality.ts rename to packages/core/src/lighting/enums/AmbientOcclusionQuality.ts index 0f83cade77..a4d8a5e0ae 100644 --- a/packages/core/src/lighting/enums/SSAOQuality.ts +++ b/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts @@ -1,7 +1,7 @@ /** - * Screen Space Ambient Occlusion quality levels. + * Ambient Occlusion quality levels. */ -export enum SSAOQuality { +export enum AmbientOcclusionQuality { /** Low quality - fewer samples, faster performance */ Low = 0, /** Medium quality - balanced samples and performance */ diff --git a/packages/core/src/lighting/index.ts b/packages/core/src/lighting/index.ts index 96a02114b5..01fbcf2961 100644 --- a/packages/core/src/lighting/index.ts +++ b/packages/core/src/lighting/index.ts @@ -4,4 +4,4 @@ export { DiffuseMode } from "./enums/DiffuseMode"; export { Light } from "./Light"; export { PointLight } from "./PointLight"; export { SpotLight } from "./SpotLight"; -export { ScreenSpaceAmbientOcclusion, SSAOQuality } from "./screenSpaceLighting"; +export { AmbientOcclusion, AmbientOcclusionQuality } from "./ambientOcclusion"; diff --git a/packages/core/src/lighting/screenSpaceLighting/index.ts b/packages/core/src/lighting/screenSpaceLighting/index.ts deleted file mode 100644 index 39a7309d3b..0000000000 --- a/packages/core/src/lighting/screenSpaceLighting/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { SSAOQuality } from "../enums/SSAOQuality"; -export { ScreenSpaceAmbientOcclusion } from "./ScreenSpaceAmbientOcclusion"; From 8136754eb9ad749f18ff6eb3c60fbfb067c8cce9 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 01:37:39 +0800 Subject: [PATCH 09/35] refactor: opt code --- .../ambientOcclusion/AmbientOcclusion.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts index 34b821d6fa..163a7ab34d 100644 --- a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts +++ b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts @@ -1,11 +1,11 @@ import { Shader, ShaderMacro, ShaderPass, ShaderProperty } from "../../shader"; import blitVs from "../../shaderlib/extra/Blit.vs.glsl"; -import scalableAmbientOcclusionFS from "./shaders/ScalableAmbientOcclusion.glsl"; -import bilateralBlurFS from "./shaders/Blur/BilateralBlur.glsl"; import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; +import bilateralBlurFS from "./shaders/Blur/BilateralBlur.glsl"; +import scalableAmbientOcclusionFS from "./shaders/ScalableAmbientOcclusion.glsl"; /** - * Screen Space Ambient Occlusion effect configuration. + * Ambient Occlusion effect configuration. */ export class AmbientOcclusion { static readonly SHADER_NAME = "ScalableAmbientOcclusion"; @@ -38,13 +38,13 @@ export class AmbientOcclusion { /** @internal */ static _enableMacro = ShaderMacro.getByName("SCENE_ENABLE_SSAO"); - private _enabled: boolean = false; - private _quality: AmbientOcclusionQuality = AmbientOcclusionQuality.Low; - private _radius: number = 0.5; - private _intensity: number = 1.0; - private _bias: number = 0.01; - private _power: number = 1.0; - private _bilateralThreshold: number = 0.05; + private _enabled = false; + private _quality = AmbientOcclusionQuality.Low; + private _radius = 0.5; + private _intensity = 1.0; + private _bias = 0.01; + private _power = 1.0; + private _bilateralThreshold = 0.05; /** * Control whether screen space ambient occlusion is enabled or not. From 138f7ca96338e14919932f67eef1b531845860a9 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 01:57:28 +0800 Subject: [PATCH 10/35] refactor: opt code --- .../core/src/lighting/enums/AmbientOcclusionQuality.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts b/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts index a4d8a5e0ae..0e12009f24 100644 --- a/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts +++ b/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts @@ -1,11 +1,11 @@ /** - * Ambient Occlusion quality levels. + * Ambient occlusion quality levels that control the balance between visual quality and performance. */ export enum AmbientOcclusionQuality { - /** Low quality - fewer samples, faster performance */ + /** Low quality - fewer samples, better performance. */ Low = 0, - /** Medium quality - balanced samples and performance */ + /** Medium quality - balanced samples and performance. */ Medium = 1, - /** High quality - more samples, better quality */ + /** High quality - more samples, better visual quality. */ High = 2 } From 765cd92a58649a0cff4cf26a6ba3b7a57d063d1d Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 02:02:16 +0800 Subject: [PATCH 11/35] refactor: opt code --- packages/core/src/lighting/enums/AmbientOcclusionQuality.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts b/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts index 0e12009f24..6e46d32803 100644 --- a/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts +++ b/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts @@ -6,6 +6,6 @@ export enum AmbientOcclusionQuality { Low = 0, /** Medium quality - balanced samples and performance. */ Medium = 1, - /** High quality - more samples, better visual quality. */ + /** High quality - more samples, slower performance. */ High = 2 } From c98a3c535ab90fc3219012639c7b72abb62c3260 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 11:59:44 +0800 Subject: [PATCH 12/35] refactor: fix e2e --- e2e/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/config.ts b/e2e/config.ts index 02a0cb6ace..b03a4eedd4 100644 --- a/e2e/config.ts +++ b/e2e/config.ts @@ -263,7 +263,7 @@ export const E2E_CONFIG = { category: "Camera", caseFileName: "camera-ssao", threshold: 0, - diffPercentage: 0.08 + diffPercentage: 0.12 } }, Physics: { From fb72f95b3462fade2bd72394504a6f42a9b2b298 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 12:51:14 +0800 Subject: [PATCH 13/35] refactor: opt code --- packages/core/src/RenderPipeline/BasicRenderPipeline.ts | 7 +++---- ...ntOcclusionPass.ts => ScalableAmbientObscurancePass.ts} | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) rename packages/core/src/lighting/ambientOcclusion/{ScreenSpaceAmbientOcclusionPass.ts => ScalableAmbientObscurancePass.ts} (98%) diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index 6ea0a90caa..9368e32c6f 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -6,6 +6,7 @@ import { BackgroundTextureFillMode } from "../enums/BackgroundTextureFillMode"; import { CameraClearFlags } from "../enums/CameraClearFlags"; import { DepthTextureMode } from "../enums/DepthTextureMode"; import { ReplacementFailureStrategy } from "../enums/ReplacementFailureStrategy"; +import { ScalableAmbientObscurancePass } from "../lighting/ambientOcclusion/ScalableAmbientObscurancePass"; import { FinalPass } from "../postProcess"; import { Shader } from "../shader/Shader"; import { ShaderMacroCollection } from "../shader/ShaderMacroCollection"; @@ -28,8 +29,6 @@ import { DepthOnlyPass } from "./DepthOnlyPass"; import { OpaqueTexturePass } from "./OpaqueTexturePass"; import { PipelineUtils } from "./PipelineUtils"; import { ContextRendererUpdateFlag, RenderContext } from "./RenderContext"; -import { SSAOPass } from "../lighting/ambientOcclusion/ScreenSpaceAmbientOcclusionPass"; -import { AmbientOcclusion } from "../lighting/ambientOcclusion"; import { RenderElement } from "./RenderElement"; import { SubRenderElement } from "./SubRenderElement"; import { PipelineStage } from "./enums/PipelineStage"; @@ -46,7 +45,7 @@ export class BasicRenderPipeline { private _internalColorTarget: RenderTarget = null; private _cascadedShadowCasterPass: CascadedShadowCasterPass; private _depthOnlyPass: DepthOnlyPass; - private _ssaoPass: SSAOPass; + private _ssaoPass: ScalableAmbientObscurancePass; private _opaqueTexturePass: OpaqueTexturePass; private _finalPass: FinalPass; private _copyBackgroundTexture: Texture2D; @@ -63,7 +62,7 @@ export class BasicRenderPipeline { this._cullingResults = new CullingResults(); this._cascadedShadowCasterPass = new CascadedShadowCasterPass(camera); this._depthOnlyPass = new DepthOnlyPass(engine); - this._ssaoPass = new SSAOPass(engine); + this._ssaoPass = new ScalableAmbientObscurancePass(engine); this._opaqueTexturePass = new OpaqueTexturePass(engine); this._finalPass = new FinalPass(engine); } diff --git a/packages/core/src/lighting/ambientOcclusion/ScreenSpaceAmbientOcclusionPass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts similarity index 98% rename from packages/core/src/lighting/ambientOcclusion/ScreenSpaceAmbientOcclusionPass.ts rename to packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index 0012eaa9ec..c231c87a1a 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScreenSpaceAmbientOcclusionPass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -14,9 +14,9 @@ import { AmbientOcclusion } from "./AmbientOcclusion"; /** * @internal - * Screen Space Ambient Occlusion render pass. + * Scalable Ambient Obscurance render pass. */ -export class SSAOPass extends PipelinePass { +export class ScalableAmbientObscurancePass extends PipelinePass { private readonly _ssaoMaterial: Material; private readonly _bilateralBlurMaterial: Material; From 4f53ba90e6b1f5491b7d2573307da6bb3e7fb080 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 13:15:09 +0800 Subject: [PATCH 14/35] refactor: opt code --- .../ScalableAmbientObscurancePass.ts | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index c231c87a1a..76ec652cfd 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -1,14 +1,14 @@ +import { Vector2, Vector4 } from "@galacean/engine-math"; import { Camera } from "../../Camera"; import { Engine } from "../../Engine"; import { Material } from "../../material"; -import { Shader, ShaderData } from "../../shader"; -import { RenderTarget, Texture2D, TextureFilterMode, TextureFormat, TextureWrapMode } from "../../texture"; import { Blitter } from "../../RenderPipeline/Blitter"; import { PipelinePass } from "../../RenderPipeline/PipelinePass"; import { PipelineUtils } from "../../RenderPipeline/PipelineUtils"; import { RenderContext } from "../../RenderPipeline/RenderContext"; -import { Vector2, Vector4 } from "@galacean/engine-math"; +import { Shader, ShaderData } from "../../shader"; import { SystemInfo } from "../../SystemInfo"; +import { RenderTarget, Texture2D, TextureFilterMode, TextureFormat, TextureWrapMode } from "../../texture"; import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; import { AmbientOcclusion } from "./AmbientOcclusion"; @@ -24,12 +24,12 @@ export class ScalableAmbientObscurancePass extends PipelinePass { private _inputRenderTarget: RenderTarget; private _blurRenderTarget: RenderTarget; - private _sampleCount: number = 7; + private _sampleCount = 7; private _position = new Vector2(); private _offsetX = new Vector4(); private _offsetY = new Vector4(); - private _quality: AmbientOcclusionQuality = AmbientOcclusionQuality.Low; + private _quality = AmbientOcclusionQuality.Low; private _kernel: Float32Array = null; constructor(engine: Engine) { @@ -40,22 +40,10 @@ export class ScalableAmbientObscurancePass extends PipelinePass { ssaoMaterial._addReferCount(1); this._ssaoMaterial = ssaoMaterial; - //Bilateral Blur material + // Bilateral Blur material const bilateralBlurMaterial = new Material(engine, Shader.find(AmbientOcclusion.SHADER_NAME)); bilateralBlurMaterial._addReferCount(1); this._bilateralBlurMaterial = bilateralBlurMaterial; - - // ShaderData initialization - const ssaoShaderData = this._ssaoMaterial.shaderData; - - const radius = 0.5; - const defaultPower = 1.0; - const peak = 0.1 * radius; - const intensity = (2 * Math.PI * peak) / this._sampleCount; - ssaoShaderData.setFloat(AmbientOcclusion._invRadiusSquaredProp, 1.0 / (radius * radius)); - ssaoShaderData.setFloat(AmbientOcclusion._intensityProp, intensity); - ssaoShaderData.setFloat(AmbientOcclusion._powerProp, defaultPower * 2.0); - ssaoShaderData.setFloat(AmbientOcclusion._peak2Prop, peak * peak); } private _setQuality(blurShaderData: ShaderData, quality: AmbientOcclusionQuality): void { @@ -180,6 +168,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { ssaoShaderData.setFloat(AmbientOcclusion._biasProp, bias); ssaoShaderData.setFloat(AmbientOcclusion._peak2Prop, peak2); ssaoShaderData.enableMacro(AmbientOcclusion._enableMacro); + debugger; blurShaderData.enableMacro(AmbientOcclusion._enableMacro); blurShaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); From 053285fc3f090d52b89ed5f02566fba06ebe2c75 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 13:27:49 +0800 Subject: [PATCH 15/35] refactor: opt code --- .../ambientOcclusion/AmbientOcclusion.ts | 2 +- .../ScalableAmbientObscurancePass.ts | 21 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts index 163a7ab34d..bef5d936f8 100644 --- a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts +++ b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts @@ -156,7 +156,7 @@ export class AmbientOcclusion { /** * @internal */ - isValid(): boolean { + _isValid(): boolean { return this.enabled && this.intensity > 0; } } diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index 76ec652cfd..f9392cf329 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -127,7 +127,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const { camera } = context; const { viewport } = camera; const scene = camera.scene; - const ssaoEffect = scene.ambientOcclusion; + const aoEffect = scene.ambientOcclusion; const ssaoShaderData = this._ssaoMaterial.shaderData; const blurShaderData = this._bilateralBlurMaterial.shaderData; const projectionMatrix = context.projectionMatrix; @@ -144,22 +144,22 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const position = this._position.set(invProjection0 * 2.0, invProjection1 * 2.0); ssaoShaderData.setVector2(AmbientOcclusion._invPositionProp, position); - if (ssaoEffect?.isValid()) { - this._setQuality(blurShaderData, ssaoEffect.quality); - const qualityValue = ssaoEffect.quality.toString(); + if (aoEffect?._isValid()) { + this._setQuality(blurShaderData, aoEffect.quality); + const qualityValue = aoEffect.quality.toString(); scene.shaderData.enableMacro("SCENE_ENABLE_SSAO"); ssaoShaderData.enableMacro("SSAO_QUALITY", qualityValue); blurShaderData.enableMacro("SSAO_QUALITY", qualityValue); - const radius = ssaoEffect.radius; + const radius = aoEffect.radius; const peak = 0.1 * radius; - const intensity = (2 * Math.PI * peak * ssaoEffect.intensity) / this._sampleCount; - const bias = ssaoEffect.bias; - const power = ssaoEffect.power * 2.0; + const intensity = (2 * Math.PI * peak * aoEffect.intensity) / this._sampleCount; + const bias = aoEffect.bias; + const power = aoEffect.power * 2.0; const projectionScaleRadius = radius * projectionMatrix.elements[5]; const peak2 = peak * peak; const invRadiusSquared = 1.0 / (radius * radius); - const farPlaneOverEdgeDistance = -camera.farClipPlane / ssaoEffect.bilateralThreshold; + const farPlaneOverEdgeDistance = -camera.farClipPlane / aoEffect.bilateralThreshold; ssaoShaderData.setFloat(AmbientOcclusion._invRadiusSquaredProp, invRadiusSquared); ssaoShaderData.setFloat(AmbientOcclusion._intensityProp, intensity); @@ -168,7 +168,6 @@ export class ScalableAmbientObscurancePass extends PipelinePass { ssaoShaderData.setFloat(AmbientOcclusion._biasProp, bias); ssaoShaderData.setFloat(AmbientOcclusion._peak2Prop, peak2); ssaoShaderData.enableMacro(AmbientOcclusion._enableMacro); - debugger; blurShaderData.enableMacro(AmbientOcclusion._enableMacro); blurShaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); @@ -182,7 +181,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const blurTarget = this._blurRenderTarget; const ssaoTarget = this._ssaoRenderTarget; - // draw ambient occlusion texture + // Draw ambient occlusion texture const sourceTexture = this._inputRenderTarget.getColorTexture(); Blitter.blitTexture(engine, sourceTexture, ssaoTarget, 0, viewport, this._ssaoMaterial, 0); From e43475431de1db368af518558d6fad0064bbbebd Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 13:40:25 +0800 Subject: [PATCH 16/35] refactor: opt code --- .../ScalableAmbientObscurancePass.ts | 55 +++++++------------ 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index f9392cf329..dd219a9fb9 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -17,10 +17,9 @@ import { AmbientOcclusion } from "./AmbientOcclusion"; * Scalable Ambient Obscurance render pass. */ export class ScalableAmbientObscurancePass extends PipelinePass { - private readonly _ssaoMaterial: Material; - private readonly _bilateralBlurMaterial: Material; + private readonly _saoMaterial: Material; - private _ssaoRenderTarget?: RenderTarget; + private _saoRenderTarget?: RenderTarget; private _inputRenderTarget: RenderTarget; private _blurRenderTarget: RenderTarget; @@ -35,15 +34,9 @@ export class ScalableAmbientObscurancePass extends PipelinePass { constructor(engine: Engine) { super(engine); - // Create SSAO material - const ssaoMaterial = new Material(engine, Shader.find(AmbientOcclusion.SHADER_NAME)); - ssaoMaterial._addReferCount(1); - this._ssaoMaterial = ssaoMaterial; - - // Bilateral Blur material - const bilateralBlurMaterial = new Material(engine, Shader.find(AmbientOcclusion.SHADER_NAME)); - bilateralBlurMaterial._addReferCount(1); - this._bilateralBlurMaterial = bilateralBlurMaterial; + const saoMaterial = new Material(engine, Shader.find(AmbientOcclusion.SHADER_NAME)); + saoMaterial._addReferCount(1); + this._saoMaterial = saoMaterial; } private _setQuality(blurShaderData: ShaderData, quality: AmbientOcclusionQuality): void { @@ -92,9 +85,9 @@ export class ScalableAmbientObscurancePass extends PipelinePass { ? TextureFormat.R8 : TextureFormat.R8G8B8; - this._ssaoRenderTarget = PipelineUtils.recreateRenderTargetIfNeeded( + this._saoRenderTarget = PipelineUtils.recreateRenderTargetIfNeeded( this.engine, - this._ssaoRenderTarget, + this._saoRenderTarget, pixelViewport.width, pixelViewport.height, textureFormat, @@ -128,8 +121,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const { viewport } = camera; const scene = camera.scene; const aoEffect = scene.ambientOcclusion; - const ssaoShaderData = this._ssaoMaterial.shaderData; - const blurShaderData = this._bilateralBlurMaterial.shaderData; + const ssaoShaderData = this._saoMaterial.shaderData; const projectionMatrix = context.projectionMatrix; // For a typical projection matrix in column-major order: @@ -145,11 +137,10 @@ export class ScalableAmbientObscurancePass extends PipelinePass { ssaoShaderData.setVector2(AmbientOcclusion._invPositionProp, position); if (aoEffect?._isValid()) { - this._setQuality(blurShaderData, aoEffect.quality); + this._setQuality(ssaoShaderData, aoEffect.quality); const qualityValue = aoEffect.quality.toString(); scene.shaderData.enableMacro("SCENE_ENABLE_SSAO"); ssaoShaderData.enableMacro("SSAO_QUALITY", qualityValue); - blurShaderData.enableMacro("SSAO_QUALITY", qualityValue); const radius = aoEffect.radius; const peak = 0.1 * radius; @@ -169,41 +160,39 @@ export class ScalableAmbientObscurancePass extends PipelinePass { ssaoShaderData.setFloat(AmbientOcclusion._peak2Prop, peak2); ssaoShaderData.enableMacro(AmbientOcclusion._enableMacro); - blurShaderData.enableMacro(AmbientOcclusion._enableMacro); - blurShaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); + ssaoShaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); } else { scene.shaderData.disableMacro("SCENE_ENABLE_SSAO"); ssaoShaderData.disableMacro(AmbientOcclusion._enableMacro); - blurShaderData.disableMacro(AmbientOcclusion._enableMacro); return; } const blurTarget = this._blurRenderTarget; - const ssaoTarget = this._ssaoRenderTarget; + const ssaoTarget = this._saoRenderTarget; // Draw ambient occlusion texture const sourceTexture = this._inputRenderTarget.getColorTexture(); - Blitter.blitTexture(engine, sourceTexture, ssaoTarget, 0, viewport, this._ssaoMaterial, 0); + Blitter.blitTexture(engine, sourceTexture, ssaoTarget, 0, viewport, this._saoMaterial, 0); // Separable bilateral blur pass - const aoTexture = this._ssaoRenderTarget.getColorTexture(); + const aoTexture = this._saoRenderTarget.getColorTexture(); // Horizontal blur: ssaoRenderTarget -> blurRenderTarget const offsetX = this._offsetX.set(1, 1, 1 / aoTexture.width, 0); const offsetY = this._offsetY.set(1, 1, 0, 1 / aoTexture.height); - Blitter.blitTexture(engine, aoTexture, blurTarget, 0, viewport, this._bilateralBlurMaterial, 1, offsetX); + Blitter.blitTexture(engine, aoTexture, blurTarget, 0, viewport, this._saoMaterial, 1, offsetX); // Vertical blur: blurRenderTarget -> ssaoRenderTarget const horizontalBlur = this._blurRenderTarget.getColorTexture(); - Blitter.blitTexture(engine, horizontalBlur, ssaoTarget, 0, viewport, this._bilateralBlurMaterial, 1, offsetY); + Blitter.blitTexture(engine, horizontalBlur, ssaoTarget, 0, viewport, this._saoMaterial, 1, offsetY); // Set the SSAO texture camera.shaderData.setTexture(Camera._cameraSSAOTextureProperty, aoTexture); } release(): void { - if (this._ssaoRenderTarget) { - this._ssaoRenderTarget.getColorTexture(0)?.destroy(true); - this._ssaoRenderTarget.destroy(true); - this._ssaoRenderTarget = null; + if (this._saoRenderTarget) { + this._saoRenderTarget.getColorTexture(0)?.destroy(true); + this._saoRenderTarget.destroy(true); + this._saoRenderTarget = null; } if (this._blurRenderTarget) { this._blurRenderTarget.getColorTexture(0)?.destroy(true); @@ -212,9 +201,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { } this._kernel = null; this._inputRenderTarget = null; - this._ssaoMaterial._addReferCount(-1); - this._ssaoMaterial.destroy(); - this._bilateralBlurMaterial._addReferCount(-1); - this._bilateralBlurMaterial.destroy(); + this._saoMaterial._addReferCount(-1); + this._saoMaterial.destroy(); } } From e7d3e68b76db6339c4cf82a768cf5d3cab669420 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 13:56:12 +0800 Subject: [PATCH 17/35] refactor: opt code --- .../ScalableAmbientObscurancePass.ts | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index dd219a9fb9..d467208c86 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -28,8 +28,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { private _offsetX = new Vector4(); private _offsetY = new Vector4(); - private _quality = AmbientOcclusionQuality.Low; - private _kernel: Float32Array = null; + private _quality: AmbientOcclusionQuality; constructor(engine: Engine) { super(engine); @@ -40,7 +39,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { } private _setQuality(blurShaderData: ShaderData, quality: AmbientOcclusionQuality): void { - if (quality === this._quality && this._kernel !== null) { + if (quality === this._quality) { return; } @@ -70,9 +69,10 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const w = Math.exp(-(i * i) / (2.0 * standardDeviation * standardDeviation)); gaussianKernel[i] = w; } - for (let i = sampleCount; i < kernelArraySize; i++) gaussianKernel[i] = 0.0; + for (let i = sampleCount; i < kernelArraySize; i++) { + gaussianKernel[i] = 0.0; + } this._quality = quality; - this._kernel = gaussianKernel; blurShaderData.setFloatArray(AmbientOcclusion._kernelProp, gaussianKernel); } @@ -121,7 +121,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const { viewport } = camera; const scene = camera.scene; const aoEffect = scene.ambientOcclusion; - const ssaoShaderData = this._saoMaterial.shaderData; + const saoShaderData = this._saoMaterial.shaderData; const projectionMatrix = context.projectionMatrix; // For a typical projection matrix in column-major order: @@ -134,13 +134,13 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const invProjection1 = 1.0 / projectionMatrix.elements[5]; // 1 / projection[1][1] const position = this._position.set(invProjection0 * 2.0, invProjection1 * 2.0); - ssaoShaderData.setVector2(AmbientOcclusion._invPositionProp, position); + saoShaderData.setVector2(AmbientOcclusion._invPositionProp, position); if (aoEffect?._isValid()) { - this._setQuality(ssaoShaderData, aoEffect.quality); + this._setQuality(saoShaderData, aoEffect.quality); const qualityValue = aoEffect.quality.toString(); scene.shaderData.enableMacro("SCENE_ENABLE_SSAO"); - ssaoShaderData.enableMacro("SSAO_QUALITY", qualityValue); + saoShaderData.enableMacro("SSAO_QUALITY", qualityValue); const radius = aoEffect.radius; const peak = 0.1 * radius; @@ -152,18 +152,18 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const invRadiusSquared = 1.0 / (radius * radius); const farPlaneOverEdgeDistance = -camera.farClipPlane / aoEffect.bilateralThreshold; - ssaoShaderData.setFloat(AmbientOcclusion._invRadiusSquaredProp, invRadiusSquared); - ssaoShaderData.setFloat(AmbientOcclusion._intensityProp, intensity); - ssaoShaderData.setFloat(AmbientOcclusion._powerProp, power); - ssaoShaderData.setFloat(AmbientOcclusion._projectionScaleRadiusProp, projectionScaleRadius); - ssaoShaderData.setFloat(AmbientOcclusion._biasProp, bias); - ssaoShaderData.setFloat(AmbientOcclusion._peak2Prop, peak2); - ssaoShaderData.enableMacro(AmbientOcclusion._enableMacro); + saoShaderData.setFloat(AmbientOcclusion._invRadiusSquaredProp, invRadiusSquared); + saoShaderData.setFloat(AmbientOcclusion._intensityProp, intensity); + saoShaderData.setFloat(AmbientOcclusion._powerProp, power); + saoShaderData.setFloat(AmbientOcclusion._projectionScaleRadiusProp, projectionScaleRadius); + saoShaderData.setFloat(AmbientOcclusion._biasProp, bias); + saoShaderData.setFloat(AmbientOcclusion._peak2Prop, peak2); + saoShaderData.enableMacro(AmbientOcclusion._enableMacro); - ssaoShaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); + saoShaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); } else { scene.shaderData.disableMacro("SCENE_ENABLE_SSAO"); - ssaoShaderData.disableMacro(AmbientOcclusion._enableMacro); + saoShaderData.disableMacro(AmbientOcclusion._enableMacro); return; } @@ -199,7 +199,6 @@ export class ScalableAmbientObscurancePass extends PipelinePass { this._blurRenderTarget.destroy(true); this._blurRenderTarget = null; } - this._kernel = null; this._inputRenderTarget = null; this._saoMaterial._addReferCount(-1); this._saoMaterial.destroy(); From 29ab104d8dc04fc496614e8949d2cff17dc997b8 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 13:59:45 +0800 Subject: [PATCH 18/35] refactor: opt code --- .../lighting/ambientOcclusion/AmbientOcclusion.ts | 12 +----------- .../ScalableAmbientObscurancePass.ts | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts index bef5d936f8..f6e87f4818 100644 --- a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts +++ b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts @@ -1,15 +1,10 @@ -import { Shader, ShaderMacro, ShaderPass, ShaderProperty } from "../../shader"; -import blitVs from "../../shaderlib/extra/Blit.vs.glsl"; +import { ShaderMacro, ShaderProperty } from "../../shader"; import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; -import bilateralBlurFS from "./shaders/Blur/BilateralBlur.glsl"; -import scalableAmbientOcclusionFS from "./shaders/ScalableAmbientOcclusion.glsl"; /** * Ambient Occlusion effect configuration. */ export class AmbientOcclusion { - static readonly SHADER_NAME = "ScalableAmbientOcclusion"; - // Shader properties for ambient occlusion calculation /** @internal */ static _invRadiusSquaredProp = ShaderProperty.getByName("material_invRadiusSquared"); @@ -160,8 +155,3 @@ export class AmbientOcclusion { return this.enabled && this.intensity > 0; } } - -Shader.create(AmbientOcclusion.SHADER_NAME, [ - new ShaderPass("ScalableAmbientOcclusion", blitVs, scalableAmbientOcclusionFS), - new ShaderPass("BilateralBlur", blitVs, bilateralBlurFS) -]); diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index d467208c86..7c97756e1f 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -6,17 +6,22 @@ import { Blitter } from "../../RenderPipeline/Blitter"; import { PipelinePass } from "../../RenderPipeline/PipelinePass"; import { PipelineUtils } from "../../RenderPipeline/PipelineUtils"; import { RenderContext } from "../../RenderPipeline/RenderContext"; -import { Shader, ShaderData } from "../../shader"; +import { Shader, ShaderData, ShaderPass } from "../../shader"; +import blitVs from "../../shaderlib/extra/Blit.vs.glsl"; import { SystemInfo } from "../../SystemInfo"; import { RenderTarget, Texture2D, TextureFilterMode, TextureFormat, TextureWrapMode } from "../../texture"; import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; import { AmbientOcclusion } from "./AmbientOcclusion"; +import bilateralBlurFS from "./shaders/Blur/BilateralBlur.glsl"; +import scalableAmbientOcclusionFS from "./shaders/ScalableAmbientOcclusion.glsl"; /** * @internal * Scalable Ambient Obscurance render pass. */ export class ScalableAmbientObscurancePass extends PipelinePass { + static readonly SHADER_NAME = "ScalableAmbientOcclusion"; + private readonly _saoMaterial: Material; private _saoRenderTarget?: RenderTarget; @@ -33,7 +38,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { constructor(engine: Engine) { super(engine); - const saoMaterial = new Material(engine, Shader.find(AmbientOcclusion.SHADER_NAME)); + const saoMaterial = new Material(engine, Shader.find(ScalableAmbientObscurancePass.SHADER_NAME)); saoMaterial._addReferCount(1); this._saoMaterial = saoMaterial; } @@ -204,3 +209,8 @@ export class ScalableAmbientObscurancePass extends PipelinePass { this._saoMaterial.destroy(); } } + +Shader.create(ScalableAmbientObscurancePass.SHADER_NAME, [ + new ShaderPass("ScalableAmbientOcclusion", blitVs, scalableAmbientOcclusionFS), + new ShaderPass("BilateralBlur", blitVs, bilateralBlurFS) +]); From e7a9a295fb08426714f89525aaba4eeda884a508 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 14:04:23 +0800 Subject: [PATCH 19/35] refactor: opt code --- .../ambientOcclusion/ScalableAmbientObscurancePass.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index 7c97756e1f..cc1af5d238 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -61,7 +61,6 @@ export class ScalableAmbientObscurancePass extends PipelinePass { standardDeviation = 8.0; break; case AmbientOcclusionQuality.High: - default: sampleCount = 16; standardDeviation = 6.0; break; @@ -70,15 +69,16 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const kernelArraySize = 16; const gaussianKernel = new Float32Array(kernelArraySize); + const variance = 2.0 * standardDeviation * standardDeviation; for (let i = 0; i < sampleCount; i++) { - const w = Math.exp(-(i * i) / (2.0 * standardDeviation * standardDeviation)); - gaussianKernel[i] = w; + gaussianKernel[i] = Math.exp(-(i * i) / variance); } for (let i = sampleCount; i < kernelArraySize; i++) { gaussianKernel[i] = 0.0; } - this._quality = quality; + blurShaderData.setFloatArray(AmbientOcclusion._kernelProp, gaussianKernel); + this._quality = quality; } onConfig(camera: Camera, inputRenderTarget: RenderTarget): void { From dd80086c146b7ccc53aa6d1503e8b074c0e042e7 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 14:19:54 +0800 Subject: [PATCH 20/35] refactor: opt code --- .../ambientOcclusion/ScalableAmbientObscurancePass.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index cc1af5d238..9865efbdb7 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -43,7 +43,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { this._saoMaterial = saoMaterial; } - private _setQuality(blurShaderData: ShaderData, quality: AmbientOcclusionQuality): void { + private _updateBlurKernel(blurShaderData: ShaderData, quality: AmbientOcclusionQuality): void { if (quality === this._quality) { return; } @@ -142,7 +142,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { saoShaderData.setVector2(AmbientOcclusion._invPositionProp, position); if (aoEffect?._isValid()) { - this._setQuality(saoShaderData, aoEffect.quality); + this._updateBlurKernel(saoShaderData, aoEffect.quality); const qualityValue = aoEffect.quality.toString(); scene.shaderData.enableMacro("SCENE_ENABLE_SSAO"); saoShaderData.enableMacro("SSAO_QUALITY", qualityValue); From 6b8c1c2fb559f965096c8aae223cd807f314dfeb Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 15:01:01 +0800 Subject: [PATCH 21/35] refactor: opt code --- .../ScalableAmbientObscurancePass.ts | 99 +++++++++---------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index 9865efbdb7..edcf9ec578 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -43,59 +43,20 @@ export class ScalableAmbientObscurancePass extends PipelinePass { this._saoMaterial = saoMaterial; } - private _updateBlurKernel(blurShaderData: ShaderData, quality: AmbientOcclusionQuality): void { - if (quality === this._quality) { - return; - } - - let sampleCount: number; - let standardDeviation: number; - - switch (quality) { - case AmbientOcclusionQuality.Low: - sampleCount = 7; - standardDeviation = 8.0; - break; - case AmbientOcclusionQuality.Medium: - sampleCount = 11; - standardDeviation = 8.0; - break; - case AmbientOcclusionQuality.High: - sampleCount = 16; - standardDeviation = 6.0; - break; - } - this._sampleCount = sampleCount; - - const kernelArraySize = 16; - const gaussianKernel = new Float32Array(kernelArraySize); - const variance = 2.0 * standardDeviation * standardDeviation; - for (let i = 0; i < sampleCount; i++) { - gaussianKernel[i] = Math.exp(-(i * i) / variance); - } - for (let i = sampleCount; i < kernelArraySize; i++) { - gaussianKernel[i] = 0.0; - } - - blurShaderData.setFloatArray(AmbientOcclusion._kernelProp, gaussianKernel); - this._quality = quality; - } - onConfig(camera: Camera, inputRenderTarget: RenderTarget): void { - const { pixelViewport } = camera; const engine = this.engine; + const { width, height } = camera.pixelViewport; + this._inputRenderTarget = inputRenderTarget; - const textureFormat = SystemInfo.supportsTextureFormat(engine, TextureFormat.R8) - ? TextureFormat.R8 - : TextureFormat.R8G8B8; + const format = SystemInfo.supportsTextureFormat(engine, TextureFormat.R8) ? TextureFormat.R8 : TextureFormat.R8G8B8; this._saoRenderTarget = PipelineUtils.recreateRenderTargetIfNeeded( - this.engine, + engine, this._saoRenderTarget, - pixelViewport.width, - pixelViewport.height, - textureFormat, + width, + height, + format, null, false, false, @@ -107,9 +68,9 @@ export class ScalableAmbientObscurancePass extends PipelinePass { this._blurRenderTarget = PipelineUtils.recreateRenderTargetIfNeeded( engine, this._blurRenderTarget, - pixelViewport.width, - pixelViewport.height, - textureFormat, + width, + height, + format, null, false, false, @@ -149,11 +110,11 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const radius = aoEffect.radius; const peak = 0.1 * radius; + const peak2 = peak * peak; const intensity = (2 * Math.PI * peak * aoEffect.intensity) / this._sampleCount; const bias = aoEffect.bias; const power = aoEffect.power * 2.0; const projectionScaleRadius = radius * projectionMatrix.elements[5]; - const peak2 = peak * peak; const invRadiusSquared = 1.0 / (radius * radius); const farPlaneOverEdgeDistance = -camera.farClipPlane / aoEffect.bilateralThreshold; @@ -208,6 +169,44 @@ export class ScalableAmbientObscurancePass extends PipelinePass { this._saoMaterial._addReferCount(-1); this._saoMaterial.destroy(); } + + private _updateBlurKernel(blurShaderData: ShaderData, quality: AmbientOcclusionQuality): void { + if (quality === this._quality) { + return; + } + + let sampleCount: number; + let standardDeviation: number; + + switch (quality) { + case AmbientOcclusionQuality.Low: + sampleCount = 7; + standardDeviation = 8.0; + break; + case AmbientOcclusionQuality.Medium: + sampleCount = 11; + standardDeviation = 8.0; + break; + case AmbientOcclusionQuality.High: + sampleCount = 16; + standardDeviation = 6.0; + break; + } + this._sampleCount = sampleCount; + + const kernelArraySize = 16; + const gaussianKernel = new Float32Array(kernelArraySize); + const variance = 2.0 * standardDeviation * standardDeviation; + for (let i = 0; i < sampleCount; i++) { + gaussianKernel[i] = Math.exp(-(i * i) / variance); + } + for (let i = sampleCount; i < kernelArraySize; i++) { + gaussianKernel[i] = 0.0; + } + + blurShaderData.setFloatArray(AmbientOcclusion._kernelProp, gaussianKernel); + this._quality = quality; + } } Shader.create(ScalableAmbientObscurancePass.SHADER_NAME, [ From bec1397aaf132d4c1441c2ca6fd8f58cd787a77d Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 15:16:58 +0800 Subject: [PATCH 22/35] refactor: opt code --- packages/core/src/Scene.ts | 5 +- .../ambientOcclusion/AmbientOcclusion.ts | 4 -- .../ScalableAmbientObscurancePass.ts | 58 +++++++++---------- 3 files changed, 31 insertions(+), 36 deletions(-) diff --git a/packages/core/src/Scene.ts b/packages/core/src/Scene.ts index 4213c71268..f4821e2b6f 100644 --- a/packages/core/src/Scene.ts +++ b/packages/core/src/Scene.ts @@ -13,7 +13,7 @@ import { AmbientLight } from "./lighting/AmbientLight"; import { LightManager } from "./lighting/LightManager"; import { PhysicsScene } from "./physics/PhysicsScene"; import { PostProcessManager } from "./postProcess"; -import { ShaderProperty } from "./shader"; +import { ShaderMacro, ShaderProperty } from "./shader"; import { ShaderData } from "./shader/ShaderData"; import { ShaderDataGroup } from "./shader/enums/ShaderDataGroup"; import { ShadowCascadesMode } from "./shadow/enum/ShadowCascadesMode"; @@ -24,6 +24,9 @@ import { ShadowType } from "./shadow/enum/ShadowType"; * Scene. */ export class Scene extends EngineObject { + /** @internal */ + static _ambientOcclusionMacro = ShaderMacro.getByName("SCENE_ENABLE_SSAO"); + private static _fogColorProperty = ShaderProperty.getByName("scene_FogColor"); private static _fogParamsProperty = ShaderProperty.getByName("scene_FogParams"); private static _prefilterdDFGProperty = ShaderProperty.getByName("scene_PrefilteredDFG"); diff --git a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts index f6e87f4818..342f20f343 100644 --- a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts +++ b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts @@ -29,10 +29,6 @@ export class AmbientOcclusion { /** @internal */ static _kernelProp = ShaderProperty.getByName("material_kernel"); - // Shader macros - /** @internal */ - static _enableMacro = ShaderMacro.getByName("SCENE_ENABLE_SSAO"); - private _enabled = false; private _quality = AmbientOcclusionQuality.Low; private _radius = 0.5; diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index edcf9ec578..a9b4882a66 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -6,6 +6,7 @@ import { Blitter } from "../../RenderPipeline/Blitter"; import { PipelinePass } from "../../RenderPipeline/PipelinePass"; import { PipelineUtils } from "../../RenderPipeline/PipelineUtils"; import { RenderContext } from "../../RenderPipeline/RenderContext"; +import { Scene } from "../../Scene"; import { Shader, ShaderData, ShaderPass } from "../../shader"; import blitVs from "../../shaderlib/extra/Blit.vs.glsl"; import { SystemInfo } from "../../SystemInfo"; @@ -44,7 +45,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { } onConfig(camera: Camera, inputRenderTarget: RenderTarget): void { - const engine = this.engine; + const { engine } = this; const { width, height } = camera.pixelViewport; this._inputRenderTarget = inputRenderTarget; @@ -84,52 +85,47 @@ export class ScalableAmbientObscurancePass extends PipelinePass { override onRender(context: RenderContext): void { const { engine } = this; const { camera } = context; - const { viewport } = camera; - const scene = camera.scene; - const aoEffect = scene.ambientOcclusion; - const saoShaderData = this._saoMaterial.shaderData; - const projectionMatrix = context.projectionMatrix; + const { viewport, scene } = camera; + const { ambientOcclusion } = scene; + const { shaderData } = this._saoMaterial; + const { projectionMatrix } = context; // For a typical projection matrix in column-major order: // projection[0][0] is at index 0 (X scaling) // projection[1][1] is at index 5 (Y scaling) // The inverse values we need are: - // invProjection[0][0] = 1 / projection[0][0] - // invProjection[1][1] = 1 / projection[1][1] - const invProjection0 = 1.0 / projectionMatrix.elements[0]; // 1 / projection[0][0] - const invProjection1 = 1.0 / projectionMatrix.elements[5]; // 1 / projection[1][1] + const invProjection0 = 1.0 / projectionMatrix.elements[0]; + const invProjection1 = 1.0 / projectionMatrix.elements[5]; const position = this._position.set(invProjection0 * 2.0, invProjection1 * 2.0); - saoShaderData.setVector2(AmbientOcclusion._invPositionProp, position); + shaderData.setVector2(AmbientOcclusion._invPositionProp, position); - if (aoEffect?._isValid()) { - this._updateBlurKernel(saoShaderData, aoEffect.quality); - const qualityValue = aoEffect.quality.toString(); - scene.shaderData.enableMacro("SCENE_ENABLE_SSAO"); - saoShaderData.enableMacro("SSAO_QUALITY", qualityValue); + if (ambientOcclusion?._isValid()) { + this._updateBlurKernel(shaderData, ambientOcclusion.quality); + const qualityValue = ambientOcclusion.quality.toString(); + scene.shaderData.enableMacro(Scene._ambientOcclusionMacro); + shaderData.enableMacro("SSAO_QUALITY", qualityValue); - const radius = aoEffect.radius; + const radius = ambientOcclusion.radius; const peak = 0.1 * radius; const peak2 = peak * peak; - const intensity = (2 * Math.PI * peak * aoEffect.intensity) / this._sampleCount; - const bias = aoEffect.bias; - const power = aoEffect.power * 2.0; + const intensity = (2 * Math.PI * peak * ambientOcclusion.intensity) / this._sampleCount; + const bias = ambientOcclusion.bias; + const power = ambientOcclusion.power * 2.0; const projectionScaleRadius = radius * projectionMatrix.elements[5]; const invRadiusSquared = 1.0 / (radius * radius); - const farPlaneOverEdgeDistance = -camera.farClipPlane / aoEffect.bilateralThreshold; + const farPlaneOverEdgeDistance = -camera.farClipPlane / ambientOcclusion.bilateralThreshold; - saoShaderData.setFloat(AmbientOcclusion._invRadiusSquaredProp, invRadiusSquared); - saoShaderData.setFloat(AmbientOcclusion._intensityProp, intensity); - saoShaderData.setFloat(AmbientOcclusion._powerProp, power); - saoShaderData.setFloat(AmbientOcclusion._projectionScaleRadiusProp, projectionScaleRadius); - saoShaderData.setFloat(AmbientOcclusion._biasProp, bias); - saoShaderData.setFloat(AmbientOcclusion._peak2Prop, peak2); - saoShaderData.enableMacro(AmbientOcclusion._enableMacro); + shaderData.setFloat(AmbientOcclusion._invRadiusSquaredProp, invRadiusSquared); + shaderData.setFloat(AmbientOcclusion._intensityProp, intensity); + shaderData.setFloat(AmbientOcclusion._powerProp, power); + shaderData.setFloat(AmbientOcclusion._projectionScaleRadiusProp, projectionScaleRadius); + shaderData.setFloat(AmbientOcclusion._biasProp, bias); + shaderData.setFloat(AmbientOcclusion._peak2Prop, peak2); - saoShaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); + shaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); } else { - scene.shaderData.disableMacro("SCENE_ENABLE_SSAO"); - saoShaderData.disableMacro(AmbientOcclusion._enableMacro); + scene.shaderData.disableMacro(Scene._ambientOcclusionMacro); return; } From c39d0f672e0f702f1df966ea7662374643778835 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 15:28:45 +0800 Subject: [PATCH 23/35] refactor: opt code --- .../ScalableAmbientObscurancePass.ts | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index a9b4882a66..907e580adf 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -23,7 +23,7 @@ import scalableAmbientOcclusionFS from "./shaders/ScalableAmbientOcclusion.glsl" export class ScalableAmbientObscurancePass extends PipelinePass { static readonly SHADER_NAME = "ScalableAmbientOcclusion"; - private readonly _saoMaterial: Material; + private readonly _material: Material; private _saoRenderTarget?: RenderTarget; private _inputRenderTarget: RenderTarget; @@ -41,7 +41,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const saoMaterial = new Material(engine, Shader.find(ScalableAmbientObscurancePass.SHADER_NAME)); saoMaterial._addReferCount(1); - this._saoMaterial = saoMaterial; + this._material = saoMaterial; } onConfig(camera: Camera, inputRenderTarget: RenderTarget): void { @@ -87,7 +87,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const { camera } = context; const { viewport, scene } = camera; const { ambientOcclusion } = scene; - const { shaderData } = this._saoMaterial; + const { shaderData } = this._material; const { projectionMatrix } = context; // For a typical projection matrix in column-major order: @@ -101,16 +101,16 @@ export class ScalableAmbientObscurancePass extends PipelinePass { shaderData.setVector2(AmbientOcclusion._invPositionProp, position); if (ambientOcclusion?._isValid()) { - this._updateBlurKernel(shaderData, ambientOcclusion.quality); - const qualityValue = ambientOcclusion.quality.toString(); scene.shaderData.enableMacro(Scene._ambientOcclusionMacro); - shaderData.enableMacro("SSAO_QUALITY", qualityValue); - const radius = ambientOcclusion.radius; + const { quality } = ambientOcclusion; + this._updateBlurKernel(shaderData, quality); + shaderData.enableMacro("SSAO_QUALITY", quality.toString()); + + const { radius, bias } = ambientOcclusion; const peak = 0.1 * radius; const peak2 = peak * peak; const intensity = (2 * Math.PI * peak * ambientOcclusion.intensity) / this._sampleCount; - const bias = ambientOcclusion.bias; const power = ambientOcclusion.power * 2.0; const projectionScaleRadius = radius * projectionMatrix.elements[5]; const invRadiusSquared = 1.0 / (radius * radius); @@ -124,30 +124,28 @@ export class ScalableAmbientObscurancePass extends PipelinePass { shaderData.setFloat(AmbientOcclusion._peak2Prop, peak2); shaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); + + const { _saoRenderTarget: saoTarget, _material: material } = this; + + // Draw ambient occlusion texture + const sourceTexture = this._inputRenderTarget.getColorTexture(); + Blitter.blitTexture(engine, sourceTexture, saoTarget, 0, viewport, material, 0); + + // Horizontal blur, saoRenderTarget -> blurRenderTarget + const aoTexture = saoTarget.getColorTexture(); + const offsetX = this._offsetX.set(1, 1, 1 / aoTexture.width, 0); + Blitter.blitTexture(engine, aoTexture, this._blurRenderTarget, 0, viewport, material, 1, offsetX); + + // Vertical blur, blurRenderTarget -> saoRenderTarget + const horizontalBlur = this._blurRenderTarget.getColorTexture(); + const offsetY = this._offsetY.set(1, 1, 0, 1 / aoTexture.height); + Blitter.blitTexture(engine, horizontalBlur, saoTarget, 0, viewport, material, 1, offsetY); + + // Set the SAO texture + camera.shaderData.setTexture(Camera._cameraSSAOTextureProperty, aoTexture); } else { scene.shaderData.disableMacro(Scene._ambientOcclusionMacro); - return; } - - const blurTarget = this._blurRenderTarget; - const ssaoTarget = this._saoRenderTarget; - - // Draw ambient occlusion texture - const sourceTexture = this._inputRenderTarget.getColorTexture(); - Blitter.blitTexture(engine, sourceTexture, ssaoTarget, 0, viewport, this._saoMaterial, 0); - - // Separable bilateral blur pass - const aoTexture = this._saoRenderTarget.getColorTexture(); - // Horizontal blur: ssaoRenderTarget -> blurRenderTarget - const offsetX = this._offsetX.set(1, 1, 1 / aoTexture.width, 0); - const offsetY = this._offsetY.set(1, 1, 0, 1 / aoTexture.height); - Blitter.blitTexture(engine, aoTexture, blurTarget, 0, viewport, this._saoMaterial, 1, offsetX); - // Vertical blur: blurRenderTarget -> ssaoRenderTarget - const horizontalBlur = this._blurRenderTarget.getColorTexture(); - Blitter.blitTexture(engine, horizontalBlur, ssaoTarget, 0, viewport, this._saoMaterial, 1, offsetY); - - // Set the SSAO texture - camera.shaderData.setTexture(Camera._cameraSSAOTextureProperty, aoTexture); } release(): void { @@ -162,8 +160,9 @@ export class ScalableAmbientObscurancePass extends PipelinePass { this._blurRenderTarget = null; } this._inputRenderTarget = null; - this._saoMaterial._addReferCount(-1); - this._saoMaterial.destroy(); + const material = this._material; + material._addReferCount(-1); + material.destroy(); } private _updateBlurKernel(blurShaderData: ShaderData, quality: AmbientOcclusionQuality): void { From f133f06fb51719362a0cb847f54c1387f86a0da9 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 15:36:16 +0800 Subject: [PATCH 24/35] refactor: opt code --- .../ambientOcclusion/AmbientOcclusion.ts | 25 ------------- .../ScalableAmbientObscurancePass.ts | 35 ++++++++++++------- 2 files changed, 23 insertions(+), 37 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts index 342f20f343..32efbbef3b 100644 --- a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts +++ b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts @@ -1,34 +1,9 @@ -import { ShaderMacro, ShaderProperty } from "../../shader"; import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; /** * Ambient Occlusion effect configuration. */ export class AmbientOcclusion { - // Shader properties for ambient occlusion calculation - /** @internal */ - static _invRadiusSquaredProp = ShaderProperty.getByName("material_invRadiusSquared"); - /** @internal */ - static _intensityProp = ShaderProperty.getByName("material_intensity"); - /** @internal */ - static _projectionScaleRadiusProp = ShaderProperty.getByName("material_projectionScaleRadius"); - /** @internal */ - static _biasProp = ShaderProperty.getByName("material_bias"); - /** @internal */ - static _minHorizonAngleSineSquaredProp = ShaderProperty.getByName("material_minHorizonAngleSineSquared"); - /** @internal */ - static _peak2Prop = ShaderProperty.getByName("material_peak2"); - /** @internal */ - static _powerProp = ShaderProperty.getByName("material_power"); - /** @internal */ - static _invPositionProp = ShaderProperty.getByName("material_invProjScaleXY"); - - // Shader properties for bilateral blur - /** @internal */ - static _farPlaneOverEdgeDistanceProp = ShaderProperty.getByName("material_farPlaneOverEdgeDistance"); - /** @internal */ - static _kernelProp = ShaderProperty.getByName("material_kernel"); - private _enabled = false; private _quality = AmbientOcclusionQuality.Low; private _radius = 0.5; diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index 907e580adf..07657ec3a5 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -7,12 +7,11 @@ import { PipelinePass } from "../../RenderPipeline/PipelinePass"; import { PipelineUtils } from "../../RenderPipeline/PipelineUtils"; import { RenderContext } from "../../RenderPipeline/RenderContext"; import { Scene } from "../../Scene"; -import { Shader, ShaderData, ShaderPass } from "../../shader"; +import { Shader, ShaderData, ShaderPass, ShaderProperty } from "../../shader"; import blitVs from "../../shaderlib/extra/Blit.vs.glsl"; import { SystemInfo } from "../../SystemInfo"; import { RenderTarget, Texture2D, TextureFilterMode, TextureFormat, TextureWrapMode } from "../../texture"; import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; -import { AmbientOcclusion } from "./AmbientOcclusion"; import bilateralBlurFS from "./shaders/Blur/BilateralBlur.glsl"; import scalableAmbientOcclusionFS from "./shaders/ScalableAmbientOcclusion.glsl"; @@ -23,6 +22,19 @@ import scalableAmbientOcclusionFS from "./shaders/ScalableAmbientOcclusion.glsl" export class ScalableAmbientObscurancePass extends PipelinePass { static readonly SHADER_NAME = "ScalableAmbientOcclusion"; + private static _invRadiusSquaredProp = ShaderProperty.getByName("material_invRadiusSquared"); + private static _intensityProp = ShaderProperty.getByName("material_intensity"); + private static _projectionScaleRadiusProp = ShaderProperty.getByName("material_projectionScaleRadius"); + private static _biasProp = ShaderProperty.getByName("material_bias"); + private static _minHorizonAngleSineSquaredProp = ShaderProperty.getByName("material_minHorizonAngleSineSquared"); + private static _peak2Prop = ShaderProperty.getByName("material_peak2"); + private static _powerProp = ShaderProperty.getByName("material_power"); + private static _invPositionProp = ShaderProperty.getByName("material_invProjScaleXY"); + + // Shader properties for bilateral blur + private static _farPlaneOverEdgeDistanceProp = ShaderProperty.getByName("material_farPlaneOverEdgeDistance"); + private static _kernelProp = ShaderProperty.getByName("material_kernel"); + private readonly _material: Material; private _saoRenderTarget?: RenderTarget; @@ -33,7 +45,6 @@ export class ScalableAmbientObscurancePass extends PipelinePass { private _position = new Vector2(); private _offsetX = new Vector4(); private _offsetY = new Vector4(); - private _quality: AmbientOcclusionQuality; constructor(engine: Engine) { @@ -98,7 +109,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const invProjection1 = 1.0 / projectionMatrix.elements[5]; const position = this._position.set(invProjection0 * 2.0, invProjection1 * 2.0); - shaderData.setVector2(AmbientOcclusion._invPositionProp, position); + shaderData.setVector2(ScalableAmbientObscurancePass._invPositionProp, position); if (ambientOcclusion?._isValid()) { scene.shaderData.enableMacro(Scene._ambientOcclusionMacro); @@ -116,14 +127,14 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const invRadiusSquared = 1.0 / (radius * radius); const farPlaneOverEdgeDistance = -camera.farClipPlane / ambientOcclusion.bilateralThreshold; - shaderData.setFloat(AmbientOcclusion._invRadiusSquaredProp, invRadiusSquared); - shaderData.setFloat(AmbientOcclusion._intensityProp, intensity); - shaderData.setFloat(AmbientOcclusion._powerProp, power); - shaderData.setFloat(AmbientOcclusion._projectionScaleRadiusProp, projectionScaleRadius); - shaderData.setFloat(AmbientOcclusion._biasProp, bias); - shaderData.setFloat(AmbientOcclusion._peak2Prop, peak2); + shaderData.setFloat(ScalableAmbientObscurancePass._invRadiusSquaredProp, invRadiusSquared); + shaderData.setFloat(ScalableAmbientObscurancePass._intensityProp, intensity); + shaderData.setFloat(ScalableAmbientObscurancePass._powerProp, power); + shaderData.setFloat(ScalableAmbientObscurancePass._projectionScaleRadiusProp, projectionScaleRadius); + shaderData.setFloat(ScalableAmbientObscurancePass._biasProp, bias); + shaderData.setFloat(ScalableAmbientObscurancePass._peak2Prop, peak2); - shaderData.setFloat(AmbientOcclusion._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); + shaderData.setFloat(ScalableAmbientObscurancePass._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); const { _saoRenderTarget: saoTarget, _material: material } = this; @@ -199,7 +210,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { gaussianKernel[i] = 0.0; } - blurShaderData.setFloatArray(AmbientOcclusion._kernelProp, gaussianKernel); + blurShaderData.setFloatArray(ScalableAmbientObscurancePass._kernelProp, gaussianKernel); this._quality = quality; } } From 4c53462e5a1f7eaaaaf4286afb446995e0d8f847 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sat, 6 Sep 2025 15:46:09 +0800 Subject: [PATCH 25/35] refactor: opt code --- .../ambientOcclusion/AmbientOcclusion.ts | 54 +++++-------------- 1 file changed, 13 insertions(+), 41 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts index 32efbbef3b..085f530dec 100644 --- a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts +++ b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts @@ -4,27 +4,10 @@ import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; * Ambient Occlusion effect configuration. */ export class AmbientOcclusion { - private _enabled = false; - private _quality = AmbientOcclusionQuality.Low; - private _radius = 0.5; - private _intensity = 1.0; - private _bias = 0.01; - private _power = 1.0; - private _bilateralThreshold = 0.05; - /** * Control whether screen space ambient occlusion is enabled or not. */ - get enabled(): boolean { - return this._enabled; - } - - set enabled(value: boolean) { - if (value === this._enabled) { - return; - } - this._enabled = value; - } + enabled = false; /** * Controls the quality of the Screen Space Ambient Occlusion. @@ -33,15 +16,19 @@ export class AmbientOcclusion { * If set to `SSAOQuality.Medium`, the effect will balance quality and performance. * If set to `SSAOQuality.High`, the effect will use more samples for better quality,but the performance will be even worse. */ - get quality(): AmbientOcclusionQuality { - return this._quality; - } + quality = AmbientOcclusionQuality.Low; - set quality(value: AmbientOcclusionQuality) { - if (this._quality !== value) { - this._quality = value; - } - } + /** + * Controls the bias to prevent self-occlusion artifacts. + * @default 0.01 + * @range [0.0, 0.1] + */ + bias = 0.01; + + private _power = 1.0; + private _bilateralThreshold = 0.05; + private _radius = 0.5; + private _intensity = 1.0; /** * Controls the radius of the Screen Space Ambient Occlusion radius. @@ -74,21 +61,6 @@ export class AmbientOcclusion { } } - /** - * Controls the bias to prevent self-occlusion artifacts. - * @default 0.01 - * @range [0.0, 0.1] - */ - get bias(): number { - return this._bias; - } - - set bias(value: number) { - if (this._bias !== value) { - this._bias = value; - } - } - /** * Control the contrast of the Screen Space Ambient Occlusion, * The larger the value, the grayer the effect. From 6bde92f13bd6db0d4033ba80b67965d1123ecaf3 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sun, 7 Sep 2025 17:51:52 +0800 Subject: [PATCH 26/35] refatcor: opt code --- packages/core/src/Scene.ts | 9 ++-- .../ambientOcclusion/AmbientOcclusion.ts | 41 ++++++++++++++++--- .../ScalableAmbientObscurancePass.ts | 5 --- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/packages/core/src/Scene.ts b/packages/core/src/Scene.ts index f4821e2b6f..2d2ef70c8a 100644 --- a/packages/core/src/Scene.ts +++ b/packages/core/src/Scene.ts @@ -8,12 +8,12 @@ import { SceneManager } from "./SceneManager"; import { EngineObject, Logger } from "./base"; import { ActiveChangeFlag } from "./enums/ActiveChangeFlag"; import { FogMode } from "./enums/FogMode"; -import { DirectLight, AmbientOcclusion } from "./lighting"; +import { AmbientOcclusion, DirectLight } from "./lighting"; import { AmbientLight } from "./lighting/AmbientLight"; import { LightManager } from "./lighting/LightManager"; import { PhysicsScene } from "./physics/PhysicsScene"; import { PostProcessManager } from "./postProcess"; -import { ShaderMacro, ShaderProperty } from "./shader"; +import { ShaderProperty } from "./shader"; import { ShaderData } from "./shader/ShaderData"; import { ShaderDataGroup } from "./shader/enums/ShaderDataGroup"; import { ShadowCascadesMode } from "./shadow/enum/ShadowCascadesMode"; @@ -24,9 +24,6 @@ import { ShadowType } from "./shadow/enum/ShadowType"; * Scene. */ export class Scene extends EngineObject { - /** @internal */ - static _ambientOcclusionMacro = ShaderMacro.getByName("SCENE_ENABLE_SSAO"); - private static _fogColorProperty = ShaderProperty.getByName("scene_FogColor"); private static _fogParamsProperty = ShaderProperty.getByName("scene_FogParams"); private static _prefilterdDFGProperty = ShaderProperty.getByName("scene_PrefilteredDFG"); @@ -62,7 +59,7 @@ export class Scene extends EngineObject { * Darkens areas where objects are close together to simulate natural light blocking, * such as corners, crevices, and contact points between surfaces. */ - readonly ambientOcclusion = new AmbientOcclusion(); + readonly ambientOcclusion = new AmbientOcclusion(this); /* @internal */ _lightManager: LightManager = new LightManager(); diff --git a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts index 085f530dec..5619cc2e22 100644 --- a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts +++ b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts @@ -1,13 +1,12 @@ +import { Scene } from "../../Scene"; +import { ShaderMacro } from "../../shader/ShaderMacro"; import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; /** * Ambient Occlusion effect configuration. */ export class AmbientOcclusion { - /** - * Control whether screen space ambient occlusion is enabled or not. - */ - enabled = false; + private static _ambientOcclusionMacro = ShaderMacro.getByName("SCENE_ENABLE_SSAO"); /** * Controls the quality of the Screen Space Ambient Occlusion. @@ -25,10 +24,26 @@ export class AmbientOcclusion { */ bias = 0.01; + private _enabled = false; private _power = 1.0; private _bilateralThreshold = 0.05; private _radius = 0.5; private _intensity = 1.0; + private _scene: Scene; + + /** + * Control whether screen space ambient occlusion is enabled or not. + */ + get enabled(): boolean { + return this._enabled; + } + + set enabled(value: boolean) { + if (this._enabled !== value) { + this._enabled = value; + this._updateShaderMacro(); + } + } /** * Controls the radius of the Screen Space Ambient Occlusion radius. @@ -58,6 +73,7 @@ export class AmbientOcclusion { set intensity(value: number) { if (this._intensity !== value) { this._intensity = Math.max(0.0, value); + this._updateShaderMacro(); } } @@ -91,10 +107,25 @@ export class AmbientOcclusion { this._bilateralThreshold = Math.max(1e-6, Math.min(1.0, value)); } + constructor(scene: Scene) { + this._scene = scene; + } + /** * @internal */ _isValid(): boolean { - return this.enabled && this.intensity > 0; + return this._enabled && this.intensity > 0; + } + + /** + * @internal + */ + private _updateShaderMacro(): void { + if (this._isValid()) { + this._scene.shaderData.enableMacro(AmbientOcclusion._ambientOcclusionMacro); + } else { + this._scene.shaderData.disableMacro(AmbientOcclusion._ambientOcclusionMacro); + } } } diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index 07657ec3a5..b8d6522ad0 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -6,7 +6,6 @@ import { Blitter } from "../../RenderPipeline/Blitter"; import { PipelinePass } from "../../RenderPipeline/PipelinePass"; import { PipelineUtils } from "../../RenderPipeline/PipelineUtils"; import { RenderContext } from "../../RenderPipeline/RenderContext"; -import { Scene } from "../../Scene"; import { Shader, ShaderData, ShaderPass, ShaderProperty } from "../../shader"; import blitVs from "../../shaderlib/extra/Blit.vs.glsl"; import { SystemInfo } from "../../SystemInfo"; @@ -112,8 +111,6 @@ export class ScalableAmbientObscurancePass extends PipelinePass { shaderData.setVector2(ScalableAmbientObscurancePass._invPositionProp, position); if (ambientOcclusion?._isValid()) { - scene.shaderData.enableMacro(Scene._ambientOcclusionMacro); - const { quality } = ambientOcclusion; this._updateBlurKernel(shaderData, quality); shaderData.enableMacro("SSAO_QUALITY", quality.toString()); @@ -154,8 +151,6 @@ export class ScalableAmbientObscurancePass extends PipelinePass { // Set the SAO texture camera.shaderData.setTexture(Camera._cameraSSAOTextureProperty, aoTexture); - } else { - scene.shaderData.disableMacro(Scene._ambientOcclusionMacro); } } From 73237d5d0f5edeff875acc45a2ac7b98fb26e370 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sun, 7 Sep 2025 18:13:26 +0800 Subject: [PATCH 27/35] refatcor: opt code --- .../ambientOcclusion/AmbientOcclusion.ts | 25 +++++++++---------- .../shaders/Blur/BilateralBlur.glsl | 4 +-- .../shaders/ScalableAmbientOcclusion.glsl | 4 +-- .../core/src/shaderlib/pbr/pbr_helper.glsl | 4 +-- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts index 5619cc2e22..9e32a3ec80 100644 --- a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts +++ b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts @@ -3,17 +3,19 @@ import { ShaderMacro } from "../../shader/ShaderMacro"; import { AmbientOcclusionQuality } from "../enums/AmbientOcclusionQuality"; /** - * Ambient Occlusion effect configuration. + * Ambient Occlusion settings. + * @remarks + * Adds realistic shadows to corners, crevices, and areas where objects meet. */ export class AmbientOcclusion { - private static _ambientOcclusionMacro = ShaderMacro.getByName("SCENE_ENABLE_SSAO"); + private static _enableMacro = ShaderMacro.getByName("SCENE_ENABLE_AMBIENT_OCCLUSION"); /** * Controls the quality of the Screen Space Ambient Occlusion. * @remarks - * If set to `SSAOQuality.Low`, the effect will use fewer samples for faster performance. - * If set to `SSAOQuality.Medium`, the effect will balance quality and performance. - * If set to `SSAOQuality.High`, the effect will use more samples for better quality,but the performance will be even worse. + * If set to `AmbientOcclusionQuality.Low`, the effect will use fewer samples for faster performance. + * If set to `AmbientOcclusionQuality.Medium`, the effect will balance quality and performance. + * If set to `AmbientOcclusionQuality.High`, the effect will use more samples for better quality,but the performance will be even worse. */ quality = AmbientOcclusionQuality.Low; @@ -41,7 +43,7 @@ export class AmbientOcclusion { set enabled(value: boolean) { if (this._enabled !== value) { this._enabled = value; - this._updateShaderMacro(); + this._toggleAmbientOcclusionMacro(); } } @@ -73,7 +75,7 @@ export class AmbientOcclusion { set intensity(value: number) { if (this._intensity !== value) { this._intensity = Math.max(0.0, value); - this._updateShaderMacro(); + this._toggleAmbientOcclusionMacro(); } } @@ -118,14 +120,11 @@ export class AmbientOcclusion { return this._enabled && this.intensity > 0; } - /** - * @internal - */ - private _updateShaderMacro(): void { + private _toggleAmbientOcclusionMacro(): void { if (this._isValid()) { - this._scene.shaderData.enableMacro(AmbientOcclusion._ambientOcclusionMacro); + this._scene.shaderData.enableMacro(AmbientOcclusion._enableMacro); } else { - this._scene.shaderData.disableMacro(AmbientOcclusion._ambientOcclusionMacro); + this._scene.shaderData.disableMacro(AmbientOcclusion._enableMacro); } } } diff --git a/packages/core/src/lighting/ambientOcclusion/shaders/Blur/BilateralBlur.glsl b/packages/core/src/lighting/ambientOcclusion/shaders/Blur/BilateralBlur.glsl index 125e549f56..0e78aa1903 100644 --- a/packages/core/src/lighting/ambientOcclusion/shaders/Blur/BilateralBlur.glsl +++ b/packages/core/src/lighting/ambientOcclusion/shaders/Blur/BilateralBlur.glsl @@ -7,7 +7,7 @@ uniform vec4 renderer_SourceScaleOffset; uniform sampler2D camera_DepthTexture; -#ifdef SCENE_ENABLE_SSAO +#ifdef SCENE_ENABLE_AMBIENT_OCCLUSION uniform float material_farPlaneOverEdgeDistance; #if SSAO_QUALITY == 0 #define SAMPLE_COUNT 7 @@ -38,7 +38,7 @@ uniform sampler2D camera_DepthTexture; void main(){ mediump vec4 color = texture2D(renderer_BlitTexture, v_uv); - #ifdef SCENE_ENABLE_SSAO + #ifdef SCENE_ENABLE_AMBIENT_OCCLUSION float depth = texture2D(camera_DepthTexture, v_uv).r; // Weight of the center pixel from the Gaussian kernel (typically 1.0) float totalWeight = material_kernel[0]; diff --git a/packages/core/src/lighting/ambientOcclusion/shaders/ScalableAmbientOcclusion.glsl b/packages/core/src/lighting/ambientOcclusion/shaders/ScalableAmbientOcclusion.glsl index 67df388612..d15594b445 100644 --- a/packages/core/src/lighting/ambientOcclusion/shaders/ScalableAmbientOcclusion.glsl +++ b/packages/core/src/lighting/ambientOcclusion/shaders/ScalableAmbientOcclusion.glsl @@ -4,7 +4,7 @@ varying vec2 v_uv; uniform vec4 renderer_texelSize; // x: 1/width, y: 1/height, z: width, w: height uniform sampler2D camera_DepthTexture; -#ifdef SCENE_ENABLE_SSAO +#ifdef SCENE_ENABLE_AMBIENT_OCCLUSION #define PI 3.14159265359 #if SSAO_QUALITY == 0 #define SAMPLE_COUNT 7.0 @@ -185,7 +185,7 @@ uniform sampler2D camera_DepthTexture; void main(){ float aoVisibility = 0.0; - #ifdef SCENE_ENABLE_SSAO + #ifdef SCENE_ENABLE_AMBIENT_OCCLUSION float depth = texture2D(camera_DepthTexture, v_uv).r; float linearDepth = SampleAndGetLinearViewDepth(depth); diff --git a/packages/core/src/shaderlib/pbr/pbr_helper.glsl b/packages/core/src/shaderlib/pbr/pbr_helper.glsl index 0c6e7026b5..12ed7ae946 100644 --- a/packages/core/src/shaderlib/pbr/pbr_helper.glsl +++ b/packages/core/src/shaderlib/pbr/pbr_helper.glsl @@ -173,14 +173,14 @@ void initMaterial(out Material material, inout Geometry geometry){ diffuseAO = ((texture2D(material_OcclusionTexture, aoUV)).r - 1.0) * material_OcclusionIntensity + 1.0; #endif - #ifdef SCENE_ENABLE_SSAO + #ifdef SCENE_ENABLE_AMBIENT_OCCLUSION vec4 samplingPositionNDC = camera_ProjMat * camera_ViewMat * vec4( geometry.position, 1.0 ); vec2 ssaoUV = (samplingPositionNDC.xy / samplingPositionNDC.w) * 0.5 + 0.5; float ssao = texture2D(camera_SSAOTexture, ssaoUV).r; diffuseAO *= ssao; #endif - #if (defined(MATERIAL_HAS_OCCLUSION_TEXTURE) || defined(SCENE_ENABLE_SSAO))&& defined(SCENE_USE_SPECULAR_ENV) + #if (defined(MATERIAL_HAS_OCCLUSION_TEXTURE) || defined(SCENE_ENABLE_AMBIENT_OCCLUSION))&& defined(SCENE_USE_SPECULAR_ENV) specularAO = saturate( pow( geometry.dotNV + diffuseAO, exp2( - 16.0 * material.roughness - 1.0 ) ) - 1.0 + diffuseAO ); #endif From 298c5ca8e6e60cf13e4d2441a56761a4ee8fd235 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sun, 7 Sep 2025 18:24:26 +0800 Subject: [PATCH 28/35] refatcor: opt code --- .../ambientOcclusion/AmbientOcclusion.ts | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts index 9e32a3ec80..b2bf20e4a2 100644 --- a/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts +++ b/packages/core/src/lighting/ambientOcclusion/AmbientOcclusion.ts @@ -11,30 +11,30 @@ export class AmbientOcclusion { private static _enableMacro = ShaderMacro.getByName("SCENE_ENABLE_AMBIENT_OCCLUSION"); /** - * Controls the quality of the Screen Space Ambient Occlusion. + * Controls the quality of the ambient occlusion effect. * @remarks * If set to `AmbientOcclusionQuality.Low`, the effect will use fewer samples for faster performance. * If set to `AmbientOcclusionQuality.Medium`, the effect will balance quality and performance. - * If set to `AmbientOcclusionQuality.High`, the effect will use more samples for better quality,but the performance will be even worse. + * If set to `AmbientOcclusionQuality.High`, the effect will use more samples for better quality, but the performance will be worse. */ quality = AmbientOcclusionQuality.Low; /** * Controls the bias to prevent self-occlusion artifacts. - * @default 0.01 - * @range [0.0, 0.1] + * Valid range: [0.0, 0.1] + * @defaultValue 0.01 */ bias = 0.01; + private _scene: Scene; private _enabled = false; private _power = 1.0; private _bilateralThreshold = 0.05; private _radius = 0.5; private _intensity = 1.0; - private _scene: Scene; /** - * Control whether screen space ambient occlusion is enabled or not. + * Control whether ambient occlusion is enabled or not. */ get enabled(): boolean { return this._enabled; @@ -48,10 +48,10 @@ export class AmbientOcclusion { } /** - * Controls the radius of the Screen Space Ambient Occlusion radius. + * Controls the radius of the ambient occlusion effect. * Higher values create larger occlusion areas. - * @default 0.5 - * @range [0.0, 10.0] + * Valid range: [0.0, 10.0] + * @defaultValue 0.5 */ get radius(): number { return this._radius; @@ -64,9 +64,9 @@ export class AmbientOcclusion { } /** - * Controls the strength of the Screen Space Ambient Occlusion effect. - * @default 1.0 - * @range [0.0, ∞) + * Controls the strength of the ambient occlusion effect. + * Valid range: [0.0, Infinity) + * @defaultValue 1.0 */ get intensity(): number { return this._intensity; @@ -80,10 +80,10 @@ export class AmbientOcclusion { } /** - * Control the contrast of the Screen Space Ambient Occlusion, + * Control the contrast of the ambient occlusion effect. * The larger the value, the grayer the effect. - * @default 1.0 - * @range [0.1, 5.0] + * Valid range: [0.1, 5.0] + * @defaultValue 1.0 */ get power(): number { return this._power; @@ -95,11 +95,10 @@ export class AmbientOcclusion { /** * Control the threshold for blurred edges. - * @remarks * Smaller value that retains the edge will result in sharper edges, * while a larger value will make the edges softer. - * @default 0.05 - * @range (0.000001, 1.0] + * Valid range: (0.000001, 1.0] + * @defaultValue 0.05 */ get bilateralThreshold(): number { return this._bilateralThreshold; From 2c22c0e6c46a3d463bcaefe0578c4b601a01e00f Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sun, 7 Sep 2025 18:26:02 +0800 Subject: [PATCH 29/35] refatcor: opt code --- packages/core/src/lighting/enums/AmbientOcclusionQuality.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts b/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts index 6e46d32803..ae2a6718da 100644 --- a/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts +++ b/packages/core/src/lighting/enums/AmbientOcclusionQuality.ts @@ -3,9 +3,9 @@ */ export enum AmbientOcclusionQuality { /** Low quality - fewer samples, better performance. */ - Low = 0, + Low, /** Medium quality - balanced samples and performance. */ - Medium = 1, + Medium, /** High quality - more samples, slower performance. */ - High = 2 + High } From 9a6cac9e2082558115110ac7a1de48e3ca0ef65b Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sun, 7 Sep 2025 19:14:20 +0800 Subject: [PATCH 30/35] refatcor: opt code --- .../src/RenderPipeline/BasicRenderPipeline.ts | 16 ++-- .../ScalableAmbientObscurancePass.ts | 88 +++++++++---------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index 9368e32c6f..ceff4f9397 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -45,7 +45,7 @@ export class BasicRenderPipeline { private _internalColorTarget: RenderTarget = null; private _cascadedShadowCasterPass: CascadedShadowCasterPass; private _depthOnlyPass: DepthOnlyPass; - private _ssaoPass: ScalableAmbientObscurancePass; + private _saoPass: ScalableAmbientObscurancePass; private _opaqueTexturePass: OpaqueTexturePass; private _finalPass: FinalPass; private _copyBackgroundTexture: Texture2D; @@ -62,7 +62,7 @@ export class BasicRenderPipeline { this._cullingResults = new CullingResults(); this._cascadedShadowCasterPass = new CascadedShadowCasterPass(camera); this._depthOnlyPass = new DepthOnlyPass(engine); - this._ssaoPass = new ScalableAmbientObscurancePass(engine); + this._saoPass = new ScalableAmbientObscurancePass(engine); this._opaqueTexturePass = new OpaqueTexturePass(engine); this._finalPass = new FinalPass(engine); } @@ -264,14 +264,16 @@ export class BasicRenderPipeline { context.setRenderTarget(colorTarget, colorViewport, mipLevel, cubeFace); } - // Screen space ambient occlusion pass + // Scalable ambient obscurance pass // Before opaque pass so materials can sample ambient occlusion in BRDF - if (scene.ambientOcclusion.enabled) { + if (scene.ambientOcclusion._isValid()) { camera.depthTextureMode = DepthTextureMode.PrePass; - const ssaoPass = this._ssaoPass; - ssaoPass.onConfig(camera, colorTarget); - ssaoPass.onRender(context); + const saoPass = this._saoPass; + saoPass.onConfig(camera, colorTarget); + saoPass.onRender(context); context.setRenderTarget(colorTarget, colorViewport, mipLevel, cubeFace); + } else { + this._saoPass.release(); } const maskManager = scene._maskManager; diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index b8d6522ad0..011f6ef737 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -49,9 +49,9 @@ export class ScalableAmbientObscurancePass extends PipelinePass { constructor(engine: Engine) { super(engine); - const saoMaterial = new Material(engine, Shader.find(ScalableAmbientObscurancePass.SHADER_NAME)); - saoMaterial._addReferCount(1); - this._material = saoMaterial; + const material = new Material(engine, Shader.find(ScalableAmbientObscurancePass.SHADER_NAME)); + material._addReferCount(1); + this._material = material; } onConfig(camera: Camera, inputRenderTarget: RenderTarget): void { @@ -110,48 +110,46 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const position = this._position.set(invProjection0 * 2.0, invProjection1 * 2.0); shaderData.setVector2(ScalableAmbientObscurancePass._invPositionProp, position); - if (ambientOcclusion?._isValid()) { - const { quality } = ambientOcclusion; - this._updateBlurKernel(shaderData, quality); - shaderData.enableMacro("SSAO_QUALITY", quality.toString()); - - const { radius, bias } = ambientOcclusion; - const peak = 0.1 * radius; - const peak2 = peak * peak; - const intensity = (2 * Math.PI * peak * ambientOcclusion.intensity) / this._sampleCount; - const power = ambientOcclusion.power * 2.0; - const projectionScaleRadius = radius * projectionMatrix.elements[5]; - const invRadiusSquared = 1.0 / (radius * radius); - const farPlaneOverEdgeDistance = -camera.farClipPlane / ambientOcclusion.bilateralThreshold; - - shaderData.setFloat(ScalableAmbientObscurancePass._invRadiusSquaredProp, invRadiusSquared); - shaderData.setFloat(ScalableAmbientObscurancePass._intensityProp, intensity); - shaderData.setFloat(ScalableAmbientObscurancePass._powerProp, power); - shaderData.setFloat(ScalableAmbientObscurancePass._projectionScaleRadiusProp, projectionScaleRadius); - shaderData.setFloat(ScalableAmbientObscurancePass._biasProp, bias); - shaderData.setFloat(ScalableAmbientObscurancePass._peak2Prop, peak2); - - shaderData.setFloat(ScalableAmbientObscurancePass._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); - - const { _saoRenderTarget: saoTarget, _material: material } = this; - - // Draw ambient occlusion texture - const sourceTexture = this._inputRenderTarget.getColorTexture(); - Blitter.blitTexture(engine, sourceTexture, saoTarget, 0, viewport, material, 0); - - // Horizontal blur, saoRenderTarget -> blurRenderTarget - const aoTexture = saoTarget.getColorTexture(); - const offsetX = this._offsetX.set(1, 1, 1 / aoTexture.width, 0); - Blitter.blitTexture(engine, aoTexture, this._blurRenderTarget, 0, viewport, material, 1, offsetX); - - // Vertical blur, blurRenderTarget -> saoRenderTarget - const horizontalBlur = this._blurRenderTarget.getColorTexture(); - const offsetY = this._offsetY.set(1, 1, 0, 1 / aoTexture.height); - Blitter.blitTexture(engine, horizontalBlur, saoTarget, 0, viewport, material, 1, offsetY); - - // Set the SAO texture - camera.shaderData.setTexture(Camera._cameraSSAOTextureProperty, aoTexture); - } + const { quality } = ambientOcclusion; + this._updateBlurKernel(shaderData, quality); + shaderData.enableMacro("SSAO_QUALITY", quality.toString()); + + const { radius, bias } = ambientOcclusion; + const peak = 0.1 * radius; + const peak2 = peak * peak; + const intensity = (2 * Math.PI * peak * ambientOcclusion.intensity) / this._sampleCount; + const power = ambientOcclusion.power * 2.0; + const projectionScaleRadius = radius * projectionMatrix.elements[5]; + const invRadiusSquared = 1.0 / (radius * radius); + const farPlaneOverEdgeDistance = -camera.farClipPlane / ambientOcclusion.bilateralThreshold; + + shaderData.setFloat(ScalableAmbientObscurancePass._invRadiusSquaredProp, invRadiusSquared); + shaderData.setFloat(ScalableAmbientObscurancePass._intensityProp, intensity); + shaderData.setFloat(ScalableAmbientObscurancePass._powerProp, power); + shaderData.setFloat(ScalableAmbientObscurancePass._projectionScaleRadiusProp, projectionScaleRadius); + shaderData.setFloat(ScalableAmbientObscurancePass._biasProp, bias); + shaderData.setFloat(ScalableAmbientObscurancePass._peak2Prop, peak2); + + shaderData.setFloat(ScalableAmbientObscurancePass._farPlaneOverEdgeDistanceProp, farPlaneOverEdgeDistance); + + const { _saoRenderTarget: saoTarget, _material: material } = this; + + // Draw ambient occlusion texture + const sourceTexture = this._inputRenderTarget.getColorTexture(); + Blitter.blitTexture(engine, sourceTexture, saoTarget, 0, viewport, material, 0); + + // Horizontal blur, saoRenderTarget -> blurRenderTarget + const aoTexture = saoTarget.getColorTexture(); + const offsetX = this._offsetX.set(1, 1, 1 / aoTexture.width, 0); + Blitter.blitTexture(engine, aoTexture, this._blurRenderTarget, 0, viewport, material, 1, offsetX); + + // Vertical blur, blurRenderTarget -> saoRenderTarget + const horizontalBlur = this._blurRenderTarget.getColorTexture(); + const offsetY = this._offsetY.set(1, 1, 0, 1 / aoTexture.height); + Blitter.blitTexture(engine, horizontalBlur, saoTarget, 0, viewport, material, 1, offsetY); + + // Set the SAO texture + camera.shaderData.setTexture(Camera._cameraSSAOTextureProperty, aoTexture); } release(): void { From 95dae2aff61794a773b79a5b801e5b6b3f6e9967 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sun, 7 Sep 2025 23:02:27 +0800 Subject: [PATCH 31/35] refactor: opt code --- .../src/RenderPipeline/BasicRenderPipeline.ts | 9 +- .../core/src/RenderPipeline/DepthOnlyPass.ts | 15 +- .../ScalableAmbientObscurancePass.ts | 10 +- .../shaders/ScalableAmbientOcclusion.glsl | 334 +++++++++--------- 4 files changed, 183 insertions(+), 185 deletions(-) diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index ceff4f9397..c1fd112569 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -92,7 +92,11 @@ export class BasicRenderPipeline { const cullingResults = this._cullingResults; const sunlight = scene._lightManager._sunlight; const depthOnlyPass = this._depthOnlyPass; - const depthPassEnabled = camera.depthTextureMode === DepthTextureMode.PrePass && depthOnlyPass._supportDepthTexture; + + // Ambient occlusion enable will force enable depth prepass + const depthPassEnabled = + (camera.depthTextureMode === DepthTextureMode.PrePass && depthOnlyPass.supportDepthTexture) || + scene.ambientOcclusion._isValid(); const finalClearFlags = camera.clearFlags & ~(ignoreClear ?? CameraClearFlags.None); const msaaSamples = renderTarget ? renderTarget.antiAliasing : camera.msaaSamples; @@ -267,9 +271,8 @@ export class BasicRenderPipeline { // Scalable ambient obscurance pass // Before opaque pass so materials can sample ambient occlusion in BRDF if (scene.ambientOcclusion._isValid()) { - camera.depthTextureMode = DepthTextureMode.PrePass; const saoPass = this._saoPass; - saoPass.onConfig(camera, colorTarget); + saoPass.onConfig(camera, this._depthOnlyPass.renderTarget); saoPass.onRender(context); context.setRenderTarget(colorTarget, colorViewport, mipLevel, cubeFace); } else { diff --git a/packages/core/src/RenderPipeline/DepthOnlyPass.ts b/packages/core/src/RenderPipeline/DepthOnlyPass.ts index 7318ee9fa0..8050ac9996 100644 --- a/packages/core/src/RenderPipeline/DepthOnlyPass.ts +++ b/packages/core/src/RenderPipeline/DepthOnlyPass.ts @@ -15,13 +15,12 @@ import { PipelineStage } from "./enums/PipelineStage"; * Depth only pass. */ export class DepthOnlyPass extends PipelinePass { - readonly _supportDepthTexture: boolean; - - private _renderTarget: RenderTarget; + readonly supportDepthTexture: boolean; + renderTarget: RenderTarget; constructor(engine: Engine) { super(engine); - this._supportDepthTexture = engine._hardwareRenderer.canIUse(GLCapabilityType.depthTexture); + this.supportDepthTexture = engine._hardwareRenderer.canIUse(GLCapabilityType.depthTexture); } onConfig(camera: Camera): void { @@ -30,7 +29,7 @@ export class DepthOnlyPass extends PipelinePass { const renderTarget = PipelineUtils.recreateRenderTargetIfNeeded( engine, - this._renderTarget, + this.renderTarget, width, height, null, @@ -43,12 +42,12 @@ export class DepthOnlyPass extends PipelinePass { TextureFilterMode.Point ); - this._renderTarget = renderTarget; + this.renderTarget = renderTarget; } override onRender(context: RenderContext, cullingResults: CullingResults): void { const engine = this.engine; - const renderTarget = this._renderTarget; + const renderTarget = this.renderTarget; const camera = context.camera; const rhi = engine._hardwareRenderer; context.setRenderTarget(renderTarget, PipelineUtils.defaultViewport, 0); @@ -58,6 +57,6 @@ export class DepthOnlyPass extends PipelinePass { cullingResults.opaqueQueue.render(context, PipelineStage.DepthOnly); cullingResults.alphaTestQueue.render(context, PipelineStage.DepthOnly); - camera.shaderData.setTexture(Camera._cameraDepthTextureProperty, this._renderTarget.depthTexture); + camera.shaderData.setTexture(Camera._cameraDepthTextureProperty, this.renderTarget.depthTexture); } } diff --git a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts index 011f6ef737..64009e52a8 100644 --- a/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts +++ b/packages/core/src/lighting/ambientOcclusion/ScalableAmbientObscurancePass.ts @@ -37,7 +37,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { private readonly _material: Material; private _saoRenderTarget?: RenderTarget; - private _inputRenderTarget: RenderTarget; + private _depthRenderTarget: RenderTarget; private _blurRenderTarget: RenderTarget; private _sampleCount = 7; @@ -54,11 +54,11 @@ export class ScalableAmbientObscurancePass extends PipelinePass { this._material = material; } - onConfig(camera: Camera, inputRenderTarget: RenderTarget): void { + onConfig(camera: Camera, depthRenderTarget: RenderTarget): void { const { engine } = this; const { width, height } = camera.pixelViewport; - this._inputRenderTarget = inputRenderTarget; + this._depthRenderTarget = depthRenderTarget; const format = SystemInfo.supportsTextureFormat(engine, TextureFormat.R8) ? TextureFormat.R8 : TextureFormat.R8G8B8; @@ -135,7 +135,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { const { _saoRenderTarget: saoTarget, _material: material } = this; // Draw ambient occlusion texture - const sourceTexture = this._inputRenderTarget.getColorTexture(); + const sourceTexture = this._depthRenderTarget.depthTexture; Blitter.blitTexture(engine, sourceTexture, saoTarget, 0, viewport, material, 0); // Horizontal blur, saoRenderTarget -> blurRenderTarget @@ -163,7 +163,7 @@ export class ScalableAmbientObscurancePass extends PipelinePass { this._blurRenderTarget.destroy(true); this._blurRenderTarget = null; } - this._inputRenderTarget = null; + this._depthRenderTarget = null; const material = this._material; material._addReferCount(-1); material.destroy(); diff --git a/packages/core/src/lighting/ambientOcclusion/shaders/ScalableAmbientOcclusion.glsl b/packages/core/src/lighting/ambientOcclusion/shaders/ScalableAmbientOcclusion.glsl index d15594b445..508d66a01d 100644 --- a/packages/core/src/lighting/ambientOcclusion/shaders/ScalableAmbientOcclusion.glsl +++ b/packages/core/src/lighting/ambientOcclusion/shaders/ScalableAmbientOcclusion.glsl @@ -2,205 +2,201 @@ varying vec2 v_uv; uniform vec4 renderer_texelSize; // x: 1/width, y: 1/height, z: width, w: height -uniform sampler2D camera_DepthTexture; - -#ifdef SCENE_ENABLE_AMBIENT_OCCLUSION - #define PI 3.14159265359 - #if SSAO_QUALITY == 0 - #define SAMPLE_COUNT 7.0 - #define SPIRAL_TURNS 3.0 - // inc = (1.0f / (SAMPLE_COUNT - 0.5f)) * SPIRAL_TURNS * 2.0 * PI - // angleIncCosSin = vec2(cos(inc), sin(inc)) - const vec2 angleIncCosSin = vec2(-0.971148, 0.238227); - #elif SSAO_QUALITY == 1 - #define SAMPLE_COUNT 11.0 - #define SPIRAL_TURNS 6.0 - const vec2 angleIncCosSin = vec2(-0.896127, -0.443780); - #elif SSAO_QUALITY == 2 - #define SAMPLE_COUNT 16.0 - #define SPIRAL_TURNS 7.0 - const vec2 angleIncCosSin = vec2(-0.966846, 0.255311); +uniform sampler2D renderer_BlitTexture; // Camera_DepthTexture + +#define PI 3.14159265359 +#if SSAO_QUALITY == 0 + #define SAMPLE_COUNT 7.0 + #define SPIRAL_TURNS 3.0 + // inc = (1.0f / (SAMPLE_COUNT - 0.5f)) * SPIRAL_TURNS * 2.0 * PI + // angleIncCosSin = vec2(cos(inc), sin(inc)) + const vec2 angleIncCosSin = vec2(-0.971148, 0.238227); +#elif SSAO_QUALITY == 1 + #define SAMPLE_COUNT 11.0 + #define SPIRAL_TURNS 6.0 + const vec2 angleIncCosSin = vec2(-0.896127, -0.443780); +#elif SSAO_QUALITY == 2 + #define SAMPLE_COUNT 16.0 + #define SPIRAL_TURNS 7.0 + const vec2 angleIncCosSin = vec2(-0.966846, 0.255311); +#endif + +uniform float material_invRadiusSquared; // Inverse of the squared radius +uniform float material_minHorizonAngleSineSquared; // Minimum horizon angle sine squared +uniform float material_intensity; // Intensity of the ambient occlusion +uniform float material_projectionScaleRadius; +uniform float material_bias; // Bias to avoid self-occlusion +uniform float material_peak2; // Peak value to avoid singularities +uniform float material_power; // Exponent to convert occlusion to visibility +uniform vec2 material_invProjScaleXY; //invProjection[0][0] * 2, invProjection[1][1] * 2 + +uniform vec4 camera_ProjectionParams; + +// maps orthographic depth buffer value (linear, [0, 1]) to view-space eye depth +float LinearDepthToViewDepth(float depth){ + return camera_ProjectionParams.y + (camera_ProjectionParams.z - camera_ProjectionParams.y) * depth; +} + +vec3 computeViewSpacePosition(vec2 uv, float linearDepth, vec2 invProjScaleXY) { + #ifdef CAMERA_ORTHOGRAPHIC + return vec3((vec2(0.5) - uv) * invProjScaleXY , linearDepth); + #else + return vec3((vec2(0.5) - uv) * invProjScaleXY * linearDepth, linearDepth); #endif +} - uniform float material_invRadiusSquared; // Inverse of the squared radius - uniform float material_minHorizonAngleSineSquared; // Minimum horizon angle sine squared - uniform float material_intensity; // Intensity of the ambient occlusion - uniform float material_projectionScaleRadius; - uniform float material_bias; // Bias to avoid self-occlusion - uniform float material_peak2; // Peak value to avoid singularities - uniform float material_power; // Exponent to convert occlusion to visibility - uniform vec2 material_invProjScaleXY; //invProjection[0][0] * 2, invProjection[1][1] * 2 +float SampleAndGetLinearViewDepth(float depth) { + #ifdef CAMERA_ORTHOGRAPHIC + return LinearDepthToViewDepth(depth); + #else + return remapDepthBufferLinear01(depth); + #endif +} - uniform vec4 camera_ProjectionParams; +vec3 computeViewSpaceNormal(vec2 uv, sampler2D depthTexture, float depth, vec2 invProjScaleXY, vec3 viewPos, vec2 sourceSize) { + vec3 normal = vec3(0.0); +#if SSAO_QUALITY == 0 || SSAO_QUALITY == 1 + vec2 uvdx = uv + vec2(sourceSize.x, 0.0); + vec2 uvdy = uv + vec2(0.0, sourceSize.y); - // maps orthographic depth buffer value (linear, [0, 1]) to view-space eye depth - float LinearDepthToViewDepth(float depth){ - return camera_ProjectionParams.y + (camera_ProjectionParams.z - camera_ProjectionParams.y) * depth; - } + float depthX = texture2D(depthTexture, uvdx).r; + float depthY = texture2D(depthTexture, uvdy).r; - vec3 computeViewSpacePosition(vec2 uv, float linearDepth, vec2 invProjScaleXY) { - #ifdef CAMERA_ORTHOGRAPHIC - return vec3((vec2(0.5) - uv) * invProjScaleXY , linearDepth); - #else - return vec3((vec2(0.5) - uv) * invProjScaleXY * linearDepth, linearDepth); - #endif - } + vec3 px = computeViewSpacePosition(uvdx, SampleAndGetLinearViewDepth(depthX), invProjScaleXY); + vec3 py = computeViewSpacePosition(uvdy, SampleAndGetLinearViewDepth(depthY), invProjScaleXY); - float SampleAndGetLinearViewDepth(float depth) { - #ifdef CAMERA_ORTHOGRAPHIC - return LinearDepthToViewDepth(depth); - #else - return remapDepthBufferLinear01(depth); - #endif - } + vec3 dpdx = px - viewPos; + vec3 dpdy = py - viewPos; - vec3 computeViewSpaceNormal(vec2 uv, sampler2D depthTexture, float depth, vec2 invProjScaleXY, vec3 viewPos, vec2 sourceSize) { - vec3 normal = vec3(0.0); - #if SSAO_QUALITY == 0 || SSAO_QUALITY == 1 - vec2 uvdx = uv + vec2(sourceSize.x, 0.0); - vec2 uvdy = uv + vec2(0.0, sourceSize.y); - - float depthX = texture2D(depthTexture, uvdx).r; - float depthY = texture2D(depthTexture, uvdy).r; - - vec3 px = computeViewSpacePosition(uvdx, SampleAndGetLinearViewDepth(depthX), invProjScaleXY); - vec3 py = computeViewSpacePosition(uvdy, SampleAndGetLinearViewDepth(depthY), invProjScaleXY); - - vec3 dpdx = px - viewPos; - vec3 dpdy = py - viewPos; - - normal = normalize(cross(dpdx, dpdy)); - - #elif SSAO_QUALITY == 2 - vec2 dx = vec2(sourceSize.x, 0.0); - vec2 dy = vec2(0.0, sourceSize.y); - - vec4 H; - H.x = texture2D(depthTexture, uv - dx).r; // left - H.y = texture2D(depthTexture, uv + dx).r; // right - H.z = texture2D(depthTexture, uv - dx * 2.0).r; // left2 - H.w = texture2D(depthTexture, uv + dx * 2.0).r; // right2 - - // Calculate horizontal edge weights - vec2 horizontalEdgeWeights = abs((2.0 * H.xy - H.zw) - depth); - - vec3 pos_l = computeViewSpacePosition(uv - dx, SampleAndGetLinearViewDepth(H.x), invProjScaleXY); - vec3 pos_r = computeViewSpacePosition(uv + dx, SampleAndGetLinearViewDepth(H.y), invProjScaleXY); - vec3 dpdx = (horizontalEdgeWeights.x < horizontalEdgeWeights.y) ? (viewPos - pos_l) : (pos_r - viewPos); - - // Sample depths for vertical edge detection - vec4 V; - V.x = texture2D(depthTexture, uv - dy).r; // down - V.y = texture2D(depthTexture, uv + dy).r; // up - V.z = texture2D(depthTexture, uv - dy * 2.0).r; // down2 - V.w = texture2D(depthTexture, uv + dy * 2.0).r; // up2 - - // Calculate vertical edge weights - vec2 verticalEdgeWeights = abs((2.0 * V.xy - V.zw) - depth); - vec3 pos_d = computeViewSpacePosition(uv - dy, SampleAndGetLinearViewDepth(V.x), invProjScaleXY); - vec3 pos_u = computeViewSpacePosition(uv + dy, SampleAndGetLinearViewDepth(V.y), invProjScaleXY); - vec3 dpdy = (verticalEdgeWeights.x < verticalEdgeWeights.y) ? (viewPos - pos_d) : (pos_u - viewPos); - normal = normalize(cross(dpdx, dpdy)); - #endif - return normal; + normal = normalize(cross(dpdx, dpdy)); - } +#elif SSAO_QUALITY == 2 + vec2 dx = vec2(sourceSize.x, 0.0); + vec2 dy = vec2(0.0, sourceSize.y); + + vec4 H; + H.x = texture2D(depthTexture, uv - dx).r; // left + H.y = texture2D(depthTexture, uv + dx).r; // right + H.z = texture2D(depthTexture, uv - dx * 2.0).r; // left2 + H.w = texture2D(depthTexture, uv + dx * 2.0).r; // right2 + + // Calculate horizontal edge weights + vec2 horizontalEdgeWeights = abs((2.0 * H.xy - H.zw) - depth); + + vec3 pos_l = computeViewSpacePosition(uv - dx, SampleAndGetLinearViewDepth(H.x), invProjScaleXY); + vec3 pos_r = computeViewSpacePosition(uv + dx, SampleAndGetLinearViewDepth(H.y), invProjScaleXY); + vec3 dpdx = (horizontalEdgeWeights.x < horizontalEdgeWeights.y) ? (viewPos - pos_l) : (pos_r - viewPos); + + // Sample depths for vertical edge detection + vec4 V; + V.x = texture2D(depthTexture, uv - dy).r; // down + V.y = texture2D(depthTexture, uv + dy).r; // up + V.z = texture2D(depthTexture, uv - dy * 2.0).r; // down2 + V.w = texture2D(depthTexture, uv + dy * 2.0).r; // up2 + + // Calculate vertical edge weights + vec2 verticalEdgeWeights = abs((2.0 * V.xy - V.zw) - depth); + vec3 pos_d = computeViewSpacePosition(uv - dy, SampleAndGetLinearViewDepth(V.x), invProjScaleXY); + vec3 pos_u = computeViewSpacePosition(uv + dy, SampleAndGetLinearViewDepth(V.y), invProjScaleXY); + vec3 dpdy = (verticalEdgeWeights.x < verticalEdgeWeights.y) ? (viewPos - pos_d) : (pos_u - viewPos); + normal = normalize(cross(dpdx, dpdy)); + #endif + return normal; - vec3 tapLocation(float i, const float noise) { - float offset = ((2.0 * PI) * 2.4) * noise; - float angle = ((i / SAMPLE_COUNT) * SPIRAL_TURNS) * (2.0 * PI) + offset; - float radius = (i + noise + 0.5) / SAMPLE_COUNT; - return vec3(cos(angle), sin(angle), radius * radius); - } +} - vec2 startPosition(const float noise) { - float angle = ((2.0 * PI) * 2.4) * noise; - return vec2(cos(angle), sin(angle)); - } +vec3 tapLocation(float i, const float noise) { + float offset = ((2.0 * PI) * 2.4) * noise; + float angle = ((i / SAMPLE_COUNT) * SPIRAL_TURNS) * (2.0 * PI) + offset; + float radius = (i + noise + 0.5) / SAMPLE_COUNT; + return vec3(cos(angle), sin(angle), radius * radius); +} - mat2 tapAngleStep() { - vec2 t = angleIncCosSin; - return mat2(t.x, t.y, -t.y, t.x); - } +vec2 startPosition(const float noise) { + float angle = ((2.0 * PI) * 2.4) * noise; + return vec2(cos(angle), sin(angle)); +} - vec3 tapLocationFast(float i, vec2 p, const float noise) { - float radius = (i + noise + 0.5) / SAMPLE_COUNT; - return vec3(p, radius * radius); - } +mat2 tapAngleStep() { + vec2 t = angleIncCosSin; + return mat2(t.x, t.y, -t.y, t.x); +} - void computeAmbientOcclusionSAO(inout float occlusion, float i, float ssDiskRadius, vec2 uv, vec3 originPosition, vec3 normal, - vec2 tapPosition, float noise, vec2 texSize) { +vec3 tapLocationFast(float i, vec2 p, const float noise) { + float radius = (i + noise + 0.5) / SAMPLE_COUNT; + return vec3(p, radius * radius); +} - vec3 tap = tapLocationFast(i, tapPosition, noise); +void computeAmbientOcclusionSAO(inout float occlusion, float i, float ssDiskRadius, vec2 uv, vec3 originPosition, vec3 normal, + vec2 tapPosition, float noise, vec2 texSize) { - float ssRadius = max(1.0, tap.z * ssDiskRadius); // at least 1 pixel screen-space radius + vec3 tap = tapLocationFast(i, tapPosition, noise); - vec2 uvSamplePos = uv + vec2(ssRadius * tap.xy) * texSize; + float ssRadius = max(1.0, tap.z * ssDiskRadius); // at least 1 pixel screen-space radius - float occlusionDepth = texture2D(camera_DepthTexture, uvSamplePos).r; - float linearOcclusionDepth = SampleAndGetLinearViewDepth(occlusionDepth); - // “p” is the position after spiral sampling - vec3 p = computeViewSpacePosition(uvSamplePos, linearOcclusionDepth, material_invProjScaleXY); + vec2 uvSamplePos = uv + vec2(ssRadius * tap.xy) * texSize; - // now we have the sample, compute AO - vec3 v = p - originPosition; // sample vector - float vv = dot(v, v); // squared distance - float vn = dot(v, normal); // distance * cos(v, normal) + float occlusionDepth = texture2D(renderer_BlitTexture, uvSamplePos).r; + float linearOcclusionDepth = SampleAndGetLinearViewDepth(occlusionDepth); + // “p” is the position after spiral sampling + vec3 p = computeViewSpacePosition(uvSamplePos, linearOcclusionDepth, material_invProjScaleXY); - // discard samples that are outside of the radius, preventing distant geometry to - // cast shadows -- there are many functions that work and choosing one is an artistic - // decision. - float weight = pow(max(0.0, 1.0 - vv * material_invRadiusSquared), 2.0); + // now we have the sample, compute AO + vec3 v = p - originPosition; // sample vector + float vv = dot(v, v); // squared distance + float vn = dot(v, normal); // distance * cos(v, normal) - // discard samples that are too close to the horizon to reduce shadows cast by geometry - // not sufficently tessellated. The goal is to discard samples that form an angle 'beta' - // smaller than 'epsilon' with the horizon. We already have dot(v,n) which is equal to the - // sin(beta) * |v|. So the test simplifies to vn^2 < vv * sin(epsilon)^2. - weight *= step(vv * material_minHorizonAngleSineSquared, vn * vn); + // discard samples that are outside of the radius, preventing distant geometry to + // cast shadows -- there are many functions that work and choosing one is an artistic + // decision. + float weight = pow(max(0.0, 1.0 - vv * material_invRadiusSquared), 2.0); - //Calculate the contribution of a single sampling point to Ambient Occlusion - float sampleOcclusion = max(0.0, vn + (originPosition.z * material_bias)) / (vv + material_peak2); - occlusion += weight * sampleOcclusion; - } + // discard samples that are too close to the horizon to reduce shadows cast by geometry + // not sufficently tessellated. The goal is to discard samples that form an angle 'beta' + // smaller than 'epsilon' with the horizon. We already have dot(v,n) which is equal to the + // sin(beta) * |v|. So the test simplifies to vn^2 < vv * sin(epsilon)^2. + weight *= step(vv * material_minHorizonAngleSineSquared, vn * vn); - void scalableAmbientObscurance(out float obscurance, vec2 fragCoord, vec2 uv, vec3 origin, vec3 normal, vec2 texSize) { - float noise = interleavedGradientNoise(fragCoord); - vec2 tapPosition = startPosition(noise); - mat2 angleStep = tapAngleStep(); - - // Choose the screen-space sample radius - // proportional to the projected area of the sphere - float ssDiskRadius = -(material_projectionScaleRadius / origin.z); - - // accumulate the occlusion amount of all sampling points - obscurance = 0.0; - for (float i = 0.0; i < SAMPLE_COUNT; i += 1.0) { - computeAmbientOcclusionSAO(obscurance, i, ssDiskRadius, uv, origin, normal, tapPosition, noise, texSize); - tapPosition = angleStep * tapPosition; - } - obscurance = sqrt(obscurance * material_intensity); + //Calculate the contribution of a single sampling point to Ambient Occlusion + float sampleOcclusion = max(0.0, vn + (originPosition.z * material_bias)) / (vv + material_peak2); + occlusion += weight * sampleOcclusion; +} + +void scalableAmbientObscurance(out float obscurance, vec2 fragCoord, vec2 uv, vec3 origin, vec3 normal, vec2 texSize) { + float noise = interleavedGradientNoise(fragCoord); + vec2 tapPosition = startPosition(noise); + mat2 angleStep = tapAngleStep(); + + // Choose the screen-space sample radius + // proportional to the projected area of the sphere + float ssDiskRadius = -(material_projectionScaleRadius / origin.z); + + // accumulate the occlusion amount of all sampling points + obscurance = 0.0; + for (float i = 0.0; i < SAMPLE_COUNT; i += 1.0) { + computeAmbientOcclusionSAO(obscurance, i, ssDiskRadius, uv, origin, normal, tapPosition, noise, texSize); + tapPosition = angleStep * tapPosition; } -#endif + obscurance = sqrt(obscurance * material_intensity); +} void main(){ float aoVisibility = 0.0; - #ifdef SCENE_ENABLE_AMBIENT_OCCLUSION - float depth = texture2D(camera_DepthTexture, v_uv).r; - float linearDepth = SampleAndGetLinearViewDepth(depth); + float depth = texture2D(renderer_BlitTexture, v_uv).r; + float linearDepth = SampleAndGetLinearViewDepth(depth); - // Reconstruct view space position from depth - vec3 viewPos = computeViewSpacePosition(v_uv, linearDepth, material_invProjScaleXY); + // Reconstruct view space position from depth + vec3 viewPos = computeViewSpacePosition(v_uv, linearDepth, material_invProjScaleXY); - // Compute normal - vec3 normal = computeViewSpaceNormal(v_uv, camera_DepthTexture, depth, material_invProjScaleXY, viewPos, renderer_texelSize.xy); - - float occlusion = 0.0; - scalableAmbientObscurance(occlusion, gl_FragCoord.xy, v_uv, viewPos, normal, renderer_texelSize.xy); + // Compute normal + vec3 normal = computeViewSpaceNormal(v_uv, renderer_BlitTexture, depth, material_invProjScaleXY, viewPos, renderer_texelSize.xy); + + float occlusion = 0.0; + scalableAmbientObscurance(occlusion, gl_FragCoord.xy, v_uv, viewPos, normal, renderer_texelSize.xy); - // occlusion to visibility - aoVisibility = pow(clamp(1.0 - occlusion, 0.0, 1.0), material_power); - #endif + // occlusion to visibility + aoVisibility = pow(clamp(1.0 - occlusion, 0.0, 1.0), material_power); gl_FragColor = vec4(aoVisibility, aoVisibility, aoVisibility, 1.0); } From eff76f723e10b98c00924d2dec9846ef7a374195 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sun, 7 Sep 2025 23:04:40 +0800 Subject: [PATCH 32/35] refactor: opt code --- packages/core/src/RenderPipeline/BasicRenderPipeline.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index c1fd112569..910307a0d7 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -94,9 +94,11 @@ export class BasicRenderPipeline { const depthOnlyPass = this._depthOnlyPass; // Ambient occlusion enable will force enable depth prepass - const depthPassEnabled = - (camera.depthTextureMode === DepthTextureMode.PrePass && depthOnlyPass.supportDepthTexture) || - scene.ambientOcclusion._isValid(); + if (scene.ambientOcclusion._isValid()) { + camera.depthTextureMode = DepthTextureMode.PrePass; + } + const depthPassEnabled = camera.depthTextureMode === DepthTextureMode.PrePass && depthOnlyPass.supportDepthTexture; + const finalClearFlags = camera.clearFlags & ~(ignoreClear ?? CameraClearFlags.None); const msaaSamples = renderTarget ? renderTarget.antiAliasing : camera.msaaSamples; From b08c08e05f073144e3b7a249db5915f84a549b12 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sun, 7 Sep 2025 23:12:16 +0800 Subject: [PATCH 33/35] refactor: opt code --- packages/core/src/RenderPipeline/BasicRenderPipeline.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index 910307a0d7..d73f731105 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -272,7 +272,7 @@ export class BasicRenderPipeline { // Scalable ambient obscurance pass // Before opaque pass so materials can sample ambient occlusion in BRDF - if (scene.ambientOcclusion._isValid()) { + if (scene.ambientOcclusion._isValid() && this._depthOnlyPass.supportDepthTexture) { const saoPass = this._saoPass; saoPass.onConfig(camera, this._depthOnlyPass.renderTarget); saoPass.onRender(context); From 5a9ce8a40029118e9ed76bf91751c7ec598bb814 Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sun, 7 Sep 2025 23:20:58 +0800 Subject: [PATCH 34/35] refactor: opt code --- .../src/RenderPipeline/BasicRenderPipeline.ts | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index d73f731105..45cc89c22c 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -92,13 +92,15 @@ export class BasicRenderPipeline { const cullingResults = this._cullingResults; const sunlight = scene._lightManager._sunlight; const depthOnlyPass = this._depthOnlyPass; + const ambientOcclusionEnabled = scene.ambientOcclusion._isValid(); + const supportDepthTexture = depthOnlyPass.supportDepthTexture; // Ambient occlusion enable will force enable depth prepass - if (scene.ambientOcclusion._isValid()) { + if (ambientOcclusionEnabled) { camera.depthTextureMode = DepthTextureMode.PrePass; } - const depthPassEnabled = camera.depthTextureMode === DepthTextureMode.PrePass && depthOnlyPass.supportDepthTexture; - + + const depthPassEnabled = camera.depthTextureMode === DepthTextureMode.PrePass && supportDepthTexture; const finalClearFlags = camera.clearFlags & ~(ignoreClear ?? CameraClearFlags.None); const msaaSamples = renderTarget ? renderTarget.antiAliasing : camera.msaaSamples; @@ -201,6 +203,16 @@ export class BasicRenderPipeline { } } + // Scalable ambient obscurance pass + // Before opaque pass so materials can sample ambient occlusion in BRDF + if (ambientOcclusionEnabled && supportDepthTexture) { + const saoPass = this._saoPass; + saoPass.onConfig(camera, this._depthOnlyPass.renderTarget); + saoPass.onRender(context); + } else { + this._saoPass.release(); + } + this._drawRenderPass(context, camera, finalClearFlags, cubeFace, mipLevel); } @@ -270,17 +282,6 @@ export class BasicRenderPipeline { context.setRenderTarget(colorTarget, colorViewport, mipLevel, cubeFace); } - // Scalable ambient obscurance pass - // Before opaque pass so materials can sample ambient occlusion in BRDF - if (scene.ambientOcclusion._isValid() && this._depthOnlyPass.supportDepthTexture) { - const saoPass = this._saoPass; - saoPass.onConfig(camera, this._depthOnlyPass.renderTarget); - saoPass.onRender(context); - context.setRenderTarget(colorTarget, colorViewport, mipLevel, cubeFace); - } else { - this._saoPass.release(); - } - const maskManager = scene._maskManager; if (finalClearFlags & CameraClearFlags.Stencil) { maskManager.hasStencilWritten = false; From 14108167e30d9e0e289b1c2b0423d051354f4b7c Mon Sep 17 00:00:00 2001 From: GuoLei1990 Date: Sun, 7 Sep 2025 23:24:53 +0800 Subject: [PATCH 35/35] refatcor: opt code --- packages/core/src/RenderPipeline/BasicRenderPipeline.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts index 45cc89c22c..c2140b4055 100644 --- a/packages/core/src/RenderPipeline/BasicRenderPipeline.ts +++ b/packages/core/src/RenderPipeline/BasicRenderPipeline.ts @@ -99,7 +99,7 @@ export class BasicRenderPipeline { if (ambientOcclusionEnabled) { camera.depthTextureMode = DepthTextureMode.PrePass; } - + const depthPassEnabled = camera.depthTextureMode === DepthTextureMode.PrePass && supportDepthTexture; const finalClearFlags = camera.clearFlags & ~(ignoreClear ?? CameraClearFlags.None); const msaaSamples = renderTarget ? renderTarget.antiAliasing : camera.msaaSamples;