reckfellENGINE

SurfaceTool: атрибуты, нормали и tangents

Порядок SetUV/SetColor/AddVertex, сглаживание, индексация и Commit без скрытого накопления.

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

Запустить цветную поверхность

Добавьте GeometryStage3D.cs и SurfaceToolLab3D.cs. Прикрепите SurfaceToolLab3D к Entity3D-корню отдельного C#-уровня 1.0.0, задайте viewport 640×420, соберите и нажмите F6. Получится квадрат с градиентом вершинных цветов, нормалями и tangents. Material включает VertexColorUseAsAlbedo.

SurfaceTool с цветами вершин и сгенерированными атрибутами

GeometryStage3D.cs
C#
using Reckfell;

public static class GeometryStage3D
{
    public static StandardMaterial3D Material(bool vertexColors = false, bool unshaded = false)
    {
        return new StandardMaterial3D
        {
            AlbedoColor = vertexColors ? Colors.White : new Color(0.24f, 0.44f, 1),
            VertexColorUseAsAlbedo = vertexColors,
            ShadingMode = unshaded ? BaseMaterial3D.ShadingModeEnum.Unshaded : BaseMaterial3D.ShadingModeEnum.PerPixel,
            Roughness = 0.8f
        };
    }

    public static void Setup(Entity3D root, string ru, string en)
    {
        root.AddChild(new WorldEnvironment { Environment = new Reckfell.Environment
        {
            BackgroundMode = Reckfell.Environment.BGMode.Color,
            BackgroundColor = new Color(0.035f, 0.04f, 0.05f),
            AmbientLightSource = Reckfell.Environment.AmbientSource.Color,
            AmbientLightColor = Colors.White, AmbientLightEnergy = 0.5f
        }});
        root.AddChild(new DirectionalLight3D { RotationDegrees = new Vector3(-55, -25, 0), LightEnergy = 1.2f });
        root.AddChild(new MeshInstance3D
        {
            Mesh = new BoxMesh { Size = new Vector3(8, 0.05f, 6) }, Position = new Vector3(0, -0.12f, 0),
            MaterialOverride = new StandardMaterial3D { AlbedoColor = new Color(0.10f, 0.11f, 0.13f), Roughness = 1 }
        });
        var camera = new Camera3D { Position = new Vector3(4, 4.8f, 6), Current = true, Fov = 45 };
        root.AddChild(camera); camera.LookAt(new Vector3(0, 0.35f, 0), Vector3.Up);
        var canvas = new CanvasLayer(); root.AddChild(canvas);
        var label = new Label { Position = new Vector2(24, 20), Text = TranslationServer.GetLocale().StartsWith("ru") ? ru : en };
        label.AddThemeFontSizeOverride("font_size", 22); canvas.AddChild(label);
    }
}
SurfaceToolLab3D.cs
C#
using Reckfell;

public partial class SurfaceToolLab3D : Entity3D
{
    public ArrayMesh Generated { get; private set; } = null!;

    public static ArrayMesh CreateQuad()
    {
        Vector3[] points = [new(-1, 0, -1), new(1, 0, -1), new(1, 0, 1), new(-1, 0, 1)];
        Vector2[] uv = [new(0, 0), new(1, 0), new(1, 1), new(0, 1)];
        Color[] colors = [new(0.24f, 0.44f, 1), new(0.5f, 0.65f, 1), Colors.White, new(0.24f, 0.44f, 1)];
        int[] indices = [0, 1, 2, 0, 2, 3];
        using var tool = new SurfaceTool();
        tool.Begin(Mesh.PrimitiveType.Triangles);
        tool.SetSmoothGroup(0);
        foreach (int index in indices)
        {
            tool.SetColor(colors[index]);
            tool.SetUV(uv[index]);
            tool.AddVertex(points[index]);
        }
        tool.GenerateNormals();
        tool.Index();
        tool.GenerateTangents();
        return tool.Commit();
    }

    public override void _Ready()
    {
        GeometryStage3D.Setup(this, "SurfaceTool: атрибуты до AddVertex", "SurfaceTool: attributes before AddVertex");
        Generated = CreateQuad();
        AddChild(new MeshInstance3D { Mesh = Generated, MaterialOverride = GeometryStage3D.Material(vertexColors: true) });
    }
}

Порядок вызовов

  1. Begin задаёт тип примитивов.
  2. SetColor, SetUV, SetNormal и другие Set-методы задают атрибуты следующей вершины.
  3. AddVertex фиксирует позицию вместе с текущими атрибутами.
  4. После построения вызовите GenerateNormals для Triangles, если не передавали корректные нормали.
  5. Index объединяет совпадающие полные наборы атрибутов. GenerateTangents требует UV, нормали и треугольники.
  6. Commit создаёт ArrayMesh либо добавляет поверхность в переданный existing.

Формат включённых атрибутов фиксируется началом выдачи вершин. Установите нужные атрибуты до первой AddVertex; впервые добавлять цвет после нескольких бесцветных вершин нельзя. Значение атрибута сохраняется до следующего Set, поэтому пропущенный SetUV может незаметно повторить предыдущее UV.

Гладкая и плоская поверхность

SetSmoothGroup(0) в примере позволяет сглаживание в одной группе. Разные группы разделяют расчёт нормалей; uint.MaxValue отключает сглаживание для плоских граней. Задавайте группу до относящихся к ней вершин и генерируйте нормали после построения. Для квадрата обе грани лежат в одной плоскости, поэтому нормали Up совпадают.

Совпавшая позиция ещё не означает одинаковую вершину: UV, цвет, нормаль и другие данные могут различаться. Index сохраняет такие разрывы. В примере после индексации остаются четыре вершины и шесть индексов; не ожидайте того же сокращения у модели со швами.

Tangents описывают направление UV для работы с tangent-space normal map. Генерация не заменяет корректную UV-развёртку и может разделять данные по швам. Проверены длина tangent-массива и его знак; произвольная UV-топология требует собственной проверки.

Не накапливать поверхности

Commit(existing) добавляет поверхность, что подтверждено отдельным вызовом в стенде. Он не заменяет прошлую геометрию и не является автоматической оптимизацией каждого кадра. Используйте Clear для нового построения самого SurfaceTool; для замены поверхности подготовьте собственный новый Mesh или явно управляйте поверхностями ArrayMesh.

Здесь проверены порядок атрибутов, цвета, нормали, tangents, индексирование, добавление поверхности и реальная отрисовка Windows/OpenGL. Создание коллайдера, экспорт и ускорение на конкретном GPU — отдельные задачи.

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

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

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

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