From 8a5611ed4cca42f42f14ae0110dd270332d26af5 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Thu, 21 May 2026 08:08:56 +0200 Subject: [PATCH] Implement advanced anti-aliasing support (FXAA/SMAA) in rendering pipeline --- src/app/App.tsx | 2 + src/rendering/advanced-rendering.ts | 65 +++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/app/App.tsx b/src/app/App.tsx index aebaf999..80ff3dea 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -198,6 +198,7 @@ import { type FaceUvState } from "../document/brushes"; import { + ADVANCED_RENDERING_ANTI_ALIASING_MODES, ADVANCED_RENDERING_DYNAMIC_GLOBAL_ILLUMINATION_QUALITIES, ADVANCED_RENDERING_WATER_REFLECTION_MODES, BOX_VOLUME_RENDER_PATHS, @@ -225,6 +226,7 @@ import { type WorldBackgroundSettings, type AdvancedRenderingSettings, type AdvancedRenderingDistanceFogSettings, + type AdvancedRenderingAntiAliasingMode, type BoxVolumeRenderPath, type AdvancedRenderingWaterReflectionMode, type AdvancedRenderingDynamicGlobalIlluminationQuality, diff --git a/src/rendering/advanced-rendering.ts b/src/rendering/advanced-rendering.ts index a76a1a3a..7f5cc2a5 100644 --- a/src/rendering/advanced-rendering.ts +++ b/src/rendering/advanced-rendering.ts @@ -28,6 +28,7 @@ import { DepthOfFieldEffect, EffectComposer, EffectPass, + FXAAEffect, NormalPass, RenderPass, ShaderPass, @@ -40,6 +41,7 @@ import { import type { AdvancedRenderingSettings, + AdvancedRenderingAntiAliasingMode, BoxVolumeRenderPath, AdvancedRenderingShadowType, AdvancedRenderingToneMappingMode @@ -246,6 +248,48 @@ export function getAdvancedRenderingToneMappingMode( } } +function getAdvancedRenderingAntiAliasingMultisampling( + renderer: WebGLRenderer, + settings: AdvancedRenderingSettings +) { + if ( + !settings.enabled || + !settings.antiAliasing.enabled || + !renderer.capabilities.isWebGL2 + ) { + return 0; + } + + switch (settings.antiAliasing.mode) { + case "msaa2x": + return 2; + case "msaa4x": + return 4; + case "msaa8x": + return 8; + case "smaa": + case "fxaa": + return 0; + } +} + +function createAdvancedRenderingAntiAliasingEffect( + mode: AdvancedRenderingAntiAliasingMode +): FXAAEffect | SMAAEffect | null { + switch (mode) { + case "smaa": + return new SMAAEffect({ + preset: SMAAPreset.MEDIUM + }); + case "fxaa": + return new FXAAEffect(); + case "msaa2x": + case "msaa4x": + case "msaa8x": + return null; + } +} + export function configureAdvancedRenderingRenderer( renderer: WebGLRenderer, settings: AdvancedRenderingSettings @@ -330,7 +374,10 @@ export function createAdvancedRenderingComposer( const composer = new EffectComposer(renderer, { depthBuffer: true, stencilBuffer: false, - multisampling: 0, + multisampling: getAdvancedRenderingAntiAliasingMultisampling( + renderer, + settings + ), frameBufferType: renderer.capabilities.isWebGL2 ? HalfFloatType : UnsignedByteType @@ -376,7 +423,7 @@ export function createAdvancedRenderingComposer( } const effects: Array< - BloomEffect | DepthOfFieldEffect | ToneMappingEffect | SMAAEffect + BloomEffect | DepthOfFieldEffect | FXAAEffect | ToneMappingEffect | SMAAEffect > = []; if (settings.ambientOcclusion.enabled || dynamicGlobalIlluminationEnabled) { @@ -523,11 +570,15 @@ export function createAdvancedRenderingComposer( mode: getAdvancedRenderingToneMappingMode(settings.toneMapping.mode) }) ); - effects.push( - new SMAAEffect({ - preset: SMAAPreset.MEDIUM - }) - ); + if (settings.antiAliasing.enabled) { + const antiAliasingEffect = createAdvancedRenderingAntiAliasingEffect( + settings.antiAliasing.mode + ); + + if (antiAliasingEffect !== null) { + effects.push(antiAliasingEffect); + } + } composer.addPass(new EffectPass(camera, ...effects));