reckfellENGINE

Сглаживание 3D: MSAA, FXAA, SMAA и TAA

Выбрать доступный метод, запустить сравнение краёв и не принять сохранённое свойство за применённый эффект.

На этой странице

Определить вид артефакта

Ступеньки по краю меша, мерцание тонкой геометрии и блики от normal map требуют разных решений. MSAA помогает геометрическим краям, но не сглаживает автоматически все детали шейдера внутри полигона. Экранные методы обрабатывают готовое изображение; временные используют историю кадров.

Сначала сравнивайте один метод на неизменной геометрии, камере и выходном разрешении. Затем проверяйте движение и целевые ассеты: красивый статический край не доказывает отсутствие ghosting или мерцания растительности.

Запустить полный пример

Сначала выполните настройку C#. Для примера нужны SDK 1.0.0, net10.0 и уровень .rscene с Entity3D-корнем. Сохраните оба файла ниже, выполните dotnet build и назначьте QualityLab3D.cs корню. Меши, камера и синий 2D-индикатор создаются кодом.

До запуска выберите экспортированное Preset: Native или Msaa4 для первого сравнения. Остальные варианты зависят от renderer. В примере настройка читается в _Ready; изменение Preset во время игры само по себе не вызывает Apply.

QualityPreset.cs
C#
using Reckfell;

public static class QualityPreset
{
    public enum Mode { Native, Msaa4, Fxaa, Smaa, Taa, HalfBilinear, HalfNearest, DoubleBilinear, FsrHalf, Fsr2Half }

    public static bool Apply(Viewport viewport, Mode mode)
    {
        if (!System.Enum.IsDefined(mode)) return false;
        string renderer = RenderingServer.GetCurrentRenderingMethod();
        bool forward = renderer == "forward_plus";
        if ((mode == Mode.Fxaa || mode == Mode.Smaa) && renderer == "gl_compatibility") return false;
        if ((mode == Mode.Taa || mode == Mode.FsrHalf || mode == Mode.Fsr2Half) && !forward) return false;
        viewport.Msaa3D = Viewport.Msaa.Disabled;
        viewport.ScreenSpaceAA = Viewport.ScreenSpaceAAEnum.Disabled;
        if (forward) viewport.UseTaa = false;
        viewport.Scaling3DMode = Viewport.Scaling3DModeEnum.Bilinear;
        viewport.Scaling3DScale = 1;
        switch (mode)
        {
            case Mode.Msaa4: viewport.Msaa3D = Viewport.Msaa.Msaa4X; break;
            case Mode.Fxaa: viewport.ScreenSpaceAA = Viewport.ScreenSpaceAAEnum.Fxaa; break;
            case Mode.Smaa: viewport.ScreenSpaceAA = Viewport.ScreenSpaceAAEnum.Smaa; break;
            case Mode.Taa: viewport.UseTaa = true; break;
            case Mode.HalfBilinear: viewport.Scaling3DScale = 0.5f; break;
            case Mode.HalfNearest:
                viewport.Scaling3DMode = Viewport.Scaling3DModeEnum.Nearest;
                viewport.Scaling3DScale = 0.5f;
                break;
            case Mode.DoubleBilinear: viewport.Scaling3DScale = 2; break;
            case Mode.FsrHalf:
                viewport.Scaling3DMode = Viewport.Scaling3DModeEnum.Fsr;
                viewport.Scaling3DScale = 0.5f;
                break;
            case Mode.Fsr2Half:
                viewport.Scaling3DMode = Viewport.Scaling3DModeEnum.Fsr2;
                viewport.Scaling3DScale = 0.5f;
                break;
        }
        return true;
    }
}
QualityLab3D.cs
C#
using Reckfell;

public partial class QualityLab3D : Entity3D
{
    [Export] public QualityPreset.Mode Preset { get; set; } = QualityPreset.Mode.Native;
    public Entity3D Geometry { get; private set; } = null!;
    public Camera3D Camera { get; private set; } = null!;
    public override void _Ready()
    {
        Geometry = new Entity3D();AddChild(Geometry);
        var white = new StandardMaterial3D
        {
            AlbedoColor = Colors.White,
            ShadingMode = BaseMaterial3D.ShadingModeEnum.Unshaded
        };
        for (int i = 0; i < 7; i++)
            Geometry.AddChild(new MeshInstance3D
            {
                Mesh = new BoxMesh { Size = new Vector3(0.035f + i * 0.025f, 3.5f, 0.1f) },
                Position = new Vector3(-2.1f + i * 0.7f, 0, 0),
                RotationDegrees = new Vector3(0, 0, 25),
                MaterialOverride = white
            });
        AddChild(new WorldEnvironment
        {
            Environment = new Reckfell.Environment
            {
                BackgroundMode = Reckfell.Environment.BGMode.Color,
                BackgroundColor = Colors.Black,
                AmbientLightSource = Reckfell.Environment.AmbientSource.Disabled,
                ReflectedLightSource = Reckfell.Environment.ReflectionSource.Disabled
            }
        });
        Camera = new Camera3D
        {
            Current = true,
            Projection = Camera3D.ProjectionType.Orthogonal,
            Size = 6,
            Position = new Vector3(0, 0, 5)
        };
        AddChild(Camera);
        var canvas = new CanvasLayer();AddChild(canvas);
        canvas.AddChild(new ColorRect
        {
            Position = new Vector2(8, 8), Size = new Vector2(80, 20),
            Color = new Color(0.08f, 0.25f, 1), MouseFilter = Control.MouseFilterEnum.Ignore
        });
        if (!QualityPreset.Apply(GetViewport(), Preset))
            ReckfellApi.PushWarning("The selected quality preset is unavailable in this renderer; viewport settings were preserved.");
    }
}

Из собственного меню вызывайте QualityPreset.Apply(viewport, mode). Метод отклоняет неподдержанный режим до изменения настроек и возвращает false; текущее состояние сохраняется. true означает выполненную настройку для выбранного renderer, а не измерение возможностей любого GPU.

Сравнить реальные края

Одноцветные наклонные 3D-полосы без сглаживания в Compatibility

Та же геометрия с MSAA 4× в Compatibility

Оригинальные кадры 512×384 текущей локальной сборки 1.0.0. На границах с MSAA появились частично покрытые пиксели; проверка исключает область синего 2D-индикатора. Изображения не увеличены фильтром и не являются скриншотами редактора.

Выбрать метод по задаче

МетодЧто делаетПоддержка и проверка
Msaa3D=Msaa4XНесколько samples для покрытия геометрического краяРеальные края проверены в Compatibility/OpenGL и Forward+/Vulkan; поддержка samples зависит от GPU
ScreenSpaceAA=FxaaБыстрый экранный фильтрТекущий API допускает Forward+/Mobile; реальный кадр проверен в Forward+
ScreenSpaceAA=SmaaЭкранная обработка контуровТекущий API допускает Forward+/Mobile; реальный кадр проверен в Forward+
UseTaa=trueВременное накопление/реконструкцияТолько Forward+; проверен статический край после накопления истории
Повышенный Scaling3DScaleРендер выше выходного разрешения с уменьшениемПроверено отдельно на scale 2; увеличивает внутреннее число пикселей

MSAA не требует истории, но расходует дополнительные буферы и обработку samples. FXAA может смягчить мелкие детали. Для TAA проверяйте движение, прозрачность, следы за объектами и смену камеры. В этом примере такая динамическая проверка не выполняется.

Для текстурного и бликового aliasing отдельно проверяйте mipmaps, фильтрацию, normal maps и roughness. Без анализа причины добавление ещё одного AA не гарантирует улучшения.

Не доверять одному getter

В текущем Compatibility присваивание ScreenSpaceAA=Fxaa сохранилось в C#-объекте, но renderer отклонил запрос, и кадр остался прежним. Аналогично UseTaa читался как true без TAA. Предупреждение движка и реальный результат важнее сохранённого значения свойства.

GetCurrentRenderingMethod возвращает gl_compatibility, forward_plus или другой текущий метод. Пример использует это для проверки доступности. MSAA 4× подтверждён на текущем ПК; наличие enum Msaa8X не доказывает поддержку любого количества samples любым устройством.

При FSR2 или другом временном upscaler не добавляйте отдельное TAA автоматически: текущий renderer отключает его внутри. QualityPreset выбирает методы раздельно и сбрасывает предыдущие настройки перед поддержанным новым режимом.

Диагностика

СимптомПроверка
FXAA/TAA включены, кадр тот жеRenderer, предупреждения и результат Apply
Края меша лучше, блики всё ещё мерцаютТекстуры/normal maps, roughness и поведение в движении
Весь кадр стал мягчеЭкранный AA и пониженный resolution scale по отдельности
Следы за движущимся объектомВременной метод и история; сравнить с MSAA/Native
Сглаживание изменило интерфейсОтличать 3D AA от отдельного 2D-rendering/UI пути

Масштабирование 3D-разрешения · Viewport API

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.