XGRIDSДокументация
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • Lixel CyberColor

    • Руководство пользователя LCC Studio

      • Начало работы
      • Версия и обновления
      • Загрузка и установка
      • Обзор интерфейса и навигация
      • Перед реконструкцией
      • Реконструкция модели
      • Реконструкция одиночной модели
      • Объединение карт
      • Воздушно-наземное объединение
      • Воздушная реконструкция
      • Мои модели
      • Другие функции
      • Настройки и учётная запись
      • Конвертер
      • Реконструкция по видео
      • Часто задаваемые вопросы
    • LCC Scene Editor

      • Версия и обновления
      • Учётная запись и вход
      • Обзор продукта и главная страница
      • Интерфейс редактора
      • Режимы навигации по сцене
      • Файл
      • Настройки
      • Операции редактирования
      • Окно
      • Глобальная панель инструментов
      • Ресурсы и свойства
      • Левая панель инструментов
      • Точки обзора
      • Портал
      • Skybox
      • Аннотации
      • Измерение
      • Flythrough
      • Отчёт по сцене
      • 3D Layout
      • Мини-карта
      • Preview Mode (Viewer)
      • Справка
      • Часто задаваемые вопросы
      • Точка появления
    • LCC Model Editor

      • Версия и обновления
      • Руководство пользователя
      • Обзор и интерфейс
      • Операции с файлами
      • Инструменты выбора
      • Редактирование моделей
      • Измерение
      • Цветокоррекция
      • Управление ресурсами
      • Настройки и справка
      • Часто задаваемые вопросы
    • Рекомендации по применению

      • Объединение нескольких крупных моделей 3DGS
  • Plugin & SDK

    • Unreal

      • Введение
      • Быстрый старт — Windows
      • Быстрый старт — Linux
      • Быстрый старт — Quest3
      • Редакции и лицензирование
      • Рендеринг
      • Растеризация Tiled (экспериментально)
      • Визуальные настройки
      • Нормали и освещение
      • Редактирование сцены
      • Параметры производительности
      • Руководство по оптимизации производительности
      • Интеграция со сторонними и движковыми плагинами
      • Прокси-меш
      • Анимация загрузки
      • Коллизии
      • Поддержка системы навигации
      • Поддержка однослойной воды
      • Локализация
      • Частые вопросы
      • Устранение неполадок
      • Журналы и диагностика
      • Свяжитесь с нами
      • Рекомендуемые практики

        • Переосвещение 3DGS с помощью меша LixelStudio
      • Справочник API

        • ALCCActorBase
        • ULCCComponentBase
        • ULCCComponent
        • ULCC2Component
        • Actor SOG / SPZ / PLY
        • ALCC2ProxyMesh
        • ALCCClippingVolume
        • ALCCSectionPlane
        • ALCCLoadVolume
        • ULCCUtilLibrary
        • Enums
        • Structs
      • Журнал изменений

        • v3.4.0
        • v3.3.1
        • v3.0.0
        • v2.2.1
        • v1.0.0
        • v0.9.0
        • v0.8.0
        • v0.7.1
        • v0.6.1
        • v0.5.2
        • v0.4.1
        • v0.4.0
        • v0.3.0
        • v0.0.5
        • v0.0.4
        • v0.0.3
        • v0.0.2
        • v0.0.1
    • Unity

      • Введение в Unity SDK
      • Технические возможности
      • Требования к среде разработки
      • Руководство по быстрому старту для PC
      • Руководство по оптимизации настроек проекта
      • Руководство по разработке для Pico 4 Ultra
      • Руководство по стримингу Pico 4 Ultra с PC
      • Руководство по разработке для Quest 3
      • Руководство по стримингу Quest 3 с PC
      • Руководство по разработке OpenXR
      • Руководство по бизнес-стримингу Pico 4 Ultra
      • Глоссарий
      • FAQ
      • Свяжитесь с нами
      • Руководство по разработке функций

        • Руководство по разработке смешанного рендеринга нескольких сцен
        • Руководство по разработке приёма теней
        • Руководство по разработке освещения в реальном времени
        • Руководство по разработке многокамерного рендеринга
        • Руководство по разработке рендеринга изображений высокого разрешения
        • Руководство по разработке совместимости форматов данных LCC и LCC2
        • Руководство по разработке эффекта загрузки
        • Руководство по разработке переключения режима рендеринга Mip
        • Руководство по разработке привязки к рёбрам и углам
        • Руководство по разработке проецируемых декалей
        • Руководство по разработке видеопроецируемой декали
        • Руководство по разработке подсветки
        • Руководство по разработке обрезки в реальном времени
        • Руководство по разработке коррекции цвета
        • Руководство по разработке получения данных Mesh сцены
        • Руководство по разработке в режиме редактора
        • Руководство по настройке параметров производительности рендеринга
        • Руководство по разработке совместной упаковки приложения и данных
        • Руководство по разработке системы коллизий
        • Руководство по проблемам с разрешениями при разработке на macOS
        • Руководство по разработке компиляции и упаковки для устройств iOS
      • Справочник по API

        • LCCManager
        • Renderer
        • Типы данных
      • Журнал изменений

        • v2.3.0
        • v2.2.10
        • v2.2.0
        • v2.1.19
        • v2.0.14

Руководство по разработке проецируемых декалей

Обзор возможностей

Проекция декали (Decal Projector) проецирует 2D-изображение на поверхность облака точек 3DGS, подобно слайд-проектору. Проектор — это фиксированный перспективный фрустум в мировом пространстве; облако точек внутри фрустума покрывается цветом декали, а облако точек вне фрустума не затрагивается. Декаль — это глобальное состояние затенения, дающее согласованный эффект затенения на всей сцене 3DGS.

Поверх базовой проекции можно дополнительно включить отсечение окклюзией. По умолчанию декаль подобна рентгену: поскольку 3DGS сам по себе не имеет понятия поверхности, декаль проникает насквозь к задним граням, окклюдированным передними объектами, и проходит через всю сцену 3DGS. После включения отсечения окклюзией окрашивается только передняя поверхность, обращённая к проектору, а окклюдированные задние грани и окклюдированные сцены больше не окрашиваются, создавая реалистичный эффект слайд-проектора.

Примечание:

Декаль и отсечение окклюзией действуют только на PC / Mac (конвейер URP). Вызовы связанных интерфейсов на платформах mobile или VR игнорируются SDK, который выводит предупреждающий журнал. Вам не нужно выполнять проверки платформ на стороне бизнес-логики, но не ожидайте увидеть эффект на этих платформах.

Шаг 1: Создайте сцену и GameObject

Создайте совершенно новую сцену в Unity. Unity по умолчанию создаёт Main Camera и Directional Light.

Настройте Main Camera

Выберите Main Camera в окне Hierarchy и задайте его свойства в окне Inspector, как показано ниже.

Настройка свойств Main Camera

Настройка свойств Main Camera

Создайте LCCManager

Щёлкните правой кнопкой мыши в пустой области окна Hierarchy, выберите Create Empty во всплывающем меню, чтобы создать пустой GameObject, назовите его LCCManager, нормализуйте его Transform и добавьте к нему скрипт LCCManager через Add Component.

Создание GameObject LCCManager и добавление скрипта LCCManager

Создание GameObject LCCManager и добавление скрипта LCCManager

Создайте LCCRenderer

Щёлкните правой кнопкой мыши в пустой области окна Hierarchy, выберите Create Empty, чтобы создать пустой GameObject, назовите его LCCRenderer и задайте его Transform значения Rotation.x = -90 и Scale.x = -1.

Создание LCCRenderer и настройка его Transform

Создание LCCRenderer и настройка его Transform (Rotation.x = -90, Scale.x = -1)

Примечание:

Настройки Transform GameObject LCCRenderer (Rotation.x = -90, Scale.x = -1) выравнивают его с системой координат данных LCC. Подробнее о выравнивании системы координат см. в разделе «Система координат данных LCC» документа Введение в Unity SDK.

Создайте Projector

Щёлкните правой кнопкой мыши в пустой области окна Hierarchy, выберите Create Empty, чтобы создать пустой GameObject с именем Projector. Цель создания этого пустого объекта — использовать его компонент Transform для управления позицией и ориентацией проектора; после связывания его с кодом скрипта вы сможете настраивать свойства проектора во время выполнения. Проектор проецирует вдоль своего направления +Z, а его свойства можно задавать по мере необходимости.

Создание пустого GameObject Projector в качестве проектора

Создание пустого GameObject Projector в качестве проектора (+Z — направление проекции)

Шаг 2: Добавьте Render Feature

  1. В строке меню Unity выберите File → Project Settings, выберите Graphics слева и подтвердите текущий Default Render Pipeline Asset. В этом примере используется URP (Universal Render Pipeline Asset).
Подтверждение Default Render Pipeline Asset в настройках Graphics

Подтверждение Default Render Pipeline Asset в настройках Graphics

  1. Щёлкните по этому Asset, найдите соответствующий файл ассета в окне Project и найдите связанный с ним Renderer (URP_Renderer.asset в этом примере).

  2. Выберите этот файл ассета Renderer, нажмите Add Renderer Feature в окне Inspector и добавьте Decal Depth Feature.

Добавление Decal Depth Feature в URP Renderer

Добавление Decal Depth Feature в URP Renderer

Примечание:

Decal Depth Feature является предпосылкой для отсечения окклюзией. Если вы используете только базовую проекцию (рентгеновскую декаль), добавлять её не нужно; но для включения отсечения окклюзией необходимо сначала зарегистрировать этот Feature в URP Renderer Asset, иначе карта глубины окклюзии не будет сгенерирована и окклюзия не вступит в силу.

Шаг 3: Напишите скрипт

Создайте новый скрипт C# с именем Decal.cs. Полный код ниже имитирует перспективу интегратора и охватывает все 7 методов, связанных с декалью (5 для базовой проекции + 2 для отсечения окклюзией); его можно скопировать непосредственно в ваш проект.

using LCCCore;
using UnityEngine;

/// <summary>
/// Проекция декали — минимальный пример использования для разработчика.
///
/// Этот скрипт имитирует «скрипт интегратора»: он вызывает только публичные API LCCManager и не затрагивает внутренности SDK.
/// Охватывает все 7 API декалей:
///   Базовая проекция (5): SetDecalEnabled / SetDecalTexture / SetDecalProjection / SetDecalOpacity / SetDecalEdgeFade
///   Отсечение окклюзией (2): SetDecalOcclusion / SetDecalOcclusionSettings
///
/// Шаги использования:
///   1) Создайте пустой GameObject и прикрепите этот скрипт;
///   2) В Inspector перетащите LCCManager из сцены в m_manager;
///   3) Задайте m_filePath действительный путь к LCC-сцене;
///   4) Перетащите проецируемое изображение в m_decalTexture (рекомендуется включить Read/Write в его настройках импорта);
///   5) Перетащите пустой объект в m_projector в качестве проектора (оставьте пустым, чтобы использовать этот объект); его ось +Z является направлением проекции;
///   6) Запустите Play. После завершения загрузки сцены декаль включится автоматически; перетаскивайте проектор, чтобы видеть декаль на облаке точек в реальном времени.
///
/// Примечание о платформах: декаль и отсечение окклюзией действуют только на PC/Mac (URP). Вызовы на mobile/VR игнорируются SDK и записываются как предупреждения.
/// </summary>
public class Decal : MonoBehaviour
{
    [Header("Обязательные")]
    [Tooltip("Экземпляр LCCManager в сцене")]
    public LCCManager m_manager;
    [Tooltip("Действительный путь к LCC-сцене")]
    public string m_filePath;
    [Tooltip("Проецируемое изображение декали. RGB=цвет, A=собственная маска декали")]
    public Texture2D m_decalTexture;

    [Header("Проектор (проецирует вдоль +Z)")]
    [Tooltip("Поза проектора. Оставьте пустым, чтобы использовать Transform этого объекта")]
    public Transform m_projector;
    [Range(1f, 179f)] public float m_fov = 60f;
    [Tooltip("Соотношение сторон проекции; при <=0 автоматически используется соотношение сторон изображения декали")]
    public float m_aspect = 0f;
    public float m_near = 0.1f;
    public float m_far = 100f;

    [Header("Внешний вид декали")]
    [Range(0f, 1f)] public float m_opacity = 1.0f;
    [Range(0f, 0.5f)][Tooltip("Ширина затухания края (отношение UV). 0 = жёсткий край")]
    public float m_edgeFade = 0.1f;
    [Tooltip("Обновлять проекцию каждый кадр, чтобы можно было перетаскивать проектор / менять параметры во время выполнения")]
    public bool m_updateEveryFrame = true;

    [Header("Отсечение окклюзией (только PC/Mac)")]
    [Tooltip("При включении задние грани/окклюдированные точки за передней геометрией больше не окрашиваются декалью (эффект слайд-проектора); при выключении — эффект рентгена")]
    public bool m_occlusion = false;
    [Range(0f, 1f)][Tooltip("Порог непрозрачности: только сплаты с непрозрачностью >= этого значения участвуют в карте глубины, отфильтровывая плавающие/туманные точки. 0 = участвуют все")]
    public float m_occlusionCutoff = 0f;
    [Range(0f, 0.5f)][Tooltip("Относительный допуск глубины. Слишком мало -> самоокклюзия у поверхности; слишком много -> утечка рентгеновского окрашивания. По умолчанию 0.05")]
    public float m_occlusionBias = 0.05f;
    [Range(0, 16)][Tooltip("Ограничение квадратного радиуса следа (px), главная ручка для устранения рентгеновского просвечивания. 0 = один тексель, по умолчанию 2")]
    public int m_occlusionFootprint = 2;
    [Tooltip("Разрешение карты глубины (px, степень двойки 256~4096). Уменьшите, чтобы заполнить дыры на скользящих углах. По умолчанию 1024")]
    public int m_occlusionResolution = 1024;

    // -- Состояние во время выполнения --
    private bool m_loaded;
    private bool m_lastOcclusion;
    private float m_lastCutoff = float.NaN;
    private float m_lastBias = float.NaN;
    private int m_lastFootprint = -1;
    private int m_lastResolution = -1;

    void Start()
    {
        if (m_manager == null || string.IsNullOrEmpty(m_filePath))
        {
            Debug.LogError("[DecalDemo] m_manager или m_filePath не назначены.");
            enabled = false;
            return;
        }

        // 1) Инициализируем рендер-конвейер в режим редактора PC для одной сцены
        m_manager.SetPlatformType(PlatformType.PC);
        m_manager.SwitchRenderPass(ActiveRenderMode.SingleRender);
        m_manager.SetEditorMode(true);

        // 2) Загружаем сцену облака точек, затем включаем декаль после завершения (декаль — глобальное состояние; безопаснее всего задавать её после готовности сцены)
        var renderer = m_manager.GetRender(this.transform);
        Debug.Log($"[DecalDemo] Начинаем загрузку: {m_filePath}");
        renderer.Load(m_filePath,
            _ => { /* обратный вызов прогресса, в примере не используется */ },
            OnSceneLoaded);
    }

    private void OnSceneLoaded()
    {
        Debug.Log("[DecalDemo] Загрузка завершена, включение проекции декали.");

        // -- Базовая проекция: 5 API --
        m_manager.SetDecalTexture(m_decalTexture);   // содержимое декали
        m_manager.SetDecalOpacity(m_opacity);        // общая непрозрачность
        m_manager.SetDecalEdgeFade(m_edgeFade);      // затухание края
        ApplyProjection();                           // поза проектора (внутри вызывает SetDecalProjection)
        m_manager.SetDecalEnabled(true);             // включаем декаль (ключевое слово _DECAL)

        // -- Отсечение окклюзией: 2 API -- должны вызываться после ApplyProjection (карте глубины нужна валидная VP проектора)
        m_manager.SetDecalOcclusionSettings(BuildOcclusionSettings());
        m_manager.SetDecalOcclusion(m_occlusion);
        CacheOcclusionState();

        m_loaded = true;
    }

    /// <summary>
    /// Только для демонстрации. В реальных проектах для лучшей производительности не нужно вызывать
    /// SetDecalProjection / SetDecalOpacity / SetDecalEdgeFade каждый кадр в Update();
    /// вызывайте соответствующий API только при изменении параметра.
    /// </summary>
    void Update()
    {
        if (!m_loaded) return;

        // переключаем окклюзию во время выполнения
        if (m_occlusion != m_lastOcclusion)
        {
            m_manager.SetDecalOcclusion(m_occlusion);
            m_lastOcclusion = m_occlusion;
        }

        // любой параметр качества окклюзии изменён -> отправляем структуру один раз
        if (!Mathf.Approximately(m_occlusionCutoff, m_lastCutoff) ||
            !Mathf.Approximately(m_occlusionBias, m_lastBias) ||
            m_occlusionFootprint != m_lastFootprint ||
            m_occlusionResolution != m_lastResolution)
        {
            m_manager.SetDecalOcclusionSettings(BuildOcclusionSettings());
            CacheOcclusionState();
        }

        // обновляем проектор / внешний вид каждый кадр для удобной отладки в реальном времени
        if (!m_updateEveryFrame) return;
        m_manager.SetDecalOpacity(m_opacity);
        m_manager.SetDecalEdgeFade(m_edgeFade);
        ApplyProjection();
    }

    /// <summary>Строит матрицу проекции из текущей позы проектора и параметров перспективы.</summary>
    private void ApplyProjection()
    {
        Transform p = m_projector != null ? m_projector : this.transform;
        float aspect = m_aspect > 0f
            ? m_aspect
            : (m_decalTexture != null ? (float)m_decalTexture.width / m_decalTexture.height : 1f);
        m_manager.SetDecalProjection(p.position, p.rotation, m_fov, aspect, m_near, m_far);
    }

    /// <summary>Собирает 4 параметра окклюзии в структуру.</summary>
    private DecalOcclusionSettings BuildOcclusionSettings()
    {
        return new DecalOcclusionSettings
        {
            opacityCutoff  = m_occlusionCutoff,
            depthBias      = m_occlusionBias,
            footprintMaxPx = m_occlusionFootprint,
            resolution     = m_occlusionResolution,
        };
    }

    private void CacheOcclusionState()
    {
        m_lastOcclusion  = m_occlusion;
        m_lastCutoff     = m_occlusionCutoff;
        m_lastBias       = m_occlusionBias;
        m_lastFootprint  = m_occlusionFootprint;
        m_lastResolution = m_occlusionResolution;
    }

    // -- Удобные точки входа для отладки (правая кнопка в Inspector) --
    [ContextMenu("Включить декаль")]  private void DecalOn()  { m_manager?.SetDecalEnabled(true); }
    [ContextMenu("Выключить декаль")] private void DecalOff() { m_manager?.SetDecalEnabled(false); }
    [ContextMenu("Включить окклюзию")]  private void OcclusionOn()  { m_occlusion = true;  m_manager?.SetDecalOcclusion(true);  m_lastOcclusion = true; }
    [ContextMenu("Выключить окклюзию")] private void OcclusionOff() { m_occlusion = false; m_manager?.SetDecalOcclusion(false); m_lastOcclusion = false; }
}

Примечание:

Декаль — это глобальное состояние затенения, и её нужно задавать после завершения загрузки LCC-сцены (то есть в обратном вызове onComplete).

В примере SetDecalTexture / SetDecalProjection / SetDecalEnabled помещены в обратный вызов завершения Load (OnSceneLoaded), чтобы не задавать их до готовности облака точек.

Связанные с отсечением окклюзией SetDecalOcclusionSettings / SetDecalOcclusion должны вызываться после ApplyProjection (то есть SetDecalProjection), потому что карте глубины окклюзии нужна валидная матрица вида-проекции проектора.

Шаг 4: Прикрепите скрипт и настройте свойства

  1. Прикрепите скрипт Decal.cs к GameObject LCCRenderer в окне Hierarchy.
  2. В окне Inspector перетащите GameObject LCCManager на свойство Manager скрипта.
  3. Перетащите GameObject Projector на свойство Projector скрипта.
  4. Заполните путь к файлу LCC в свойстве File Path скрипта и перетащите изображение текстуры декали на свойство Decal Texture.
  5. Остальные параметры свойств можно настроить по мере необходимости; значение каждого свойства показано в таблице ниже.
Настройки свойств Inspector для скрипта Decal

Настройки свойств Inspector для скрипта Decal

ПолеЗначениеЗначение по умолчанию
ManagerЭкземпляр LCCManager в сценеОбязательное
File PathДействительный путь к LCC-сценеОбязательное
Decal TextureПроецируемое изображение декали, RGB — цвет, A — собственная маска декалиОбязательное
ProjectorПоза проектора, +Z — направление проекции; пусто — используется Transform этого объектаПусто
FovПерспективное поле зрения проектора60
AspectСоотношение сторон проекции; при значении меньше или равном 0 вычисляется автоматически из соотношения сторон изображения декали0 (авто)
Near / FarБлижняя / дальняя плоскости отсечения фрустума проектора0.1 / 100
OpacityОбщая непрозрачность декали1
Edge FadeШирина затухания края (отношение UV), 0 — жёсткий край0.1
Update Every FrameОбновлять проекцию каждый кадр, удобно для перетаскивания проектора или изменения параметров во время выполненияОтмечено
OcclusionВключать ли отсечение окклюзиейВыкл
Occlusion CutoffПорог непрозрачности; только сплаты с непрозрачностью не ниже этого значения участвуют в карте глубины0
Occlusion BiasОтносительный допуск глубины0.05
Occlusion FootprintОграничение квадратного радиуса следа (px), главная ручка для устранения рентгеновского просвечивания2
Occlusion ResolutionРазрешение карты глубины окклюзии (px, степень двойки 256~4096)1024

Шаг 5: Запустите и наблюдайте эффект

Нажмите кнопку Play в Unity. После завершения загрузки сцены декаль включится автоматически. При отмеченном Update Every Frame вы можете во время выполнения напрямую перетаскивать объект проектора в окне Scene и видеть движение декали по поверхности 3DGS в реальном времени; настройка параметров, таких как Opacity и Edge Fade, также вступает в силу немедленно. Контекстное меню компонента скрипта также предоставляет четыре ярлыка — Decal On/Off и Occlusion On/Off — для удобной проверки эффекта включения/выключения по отдельности.

Декаль, спроецированная на поверхность 3DGS после запуска (базовая проекция)

Декаль, спроецированная на поверхность 3DGS после запуска (базовая проекция, рентгеновское проникновение)

После включения отсечения окклюзией окрашивается только передняя поверхность, обращённая к проектору

После включения отсечения окклюзией окрашивается только передняя поверхность, обращённая к проектору (эффект слайд-проектора)

FAQ: Отключите режим совместимости

Если окно Console Unity сообщает об ошибках и эффект декали не появляется, отключите режим совместимости: откройте панель настроек через Edit → Project Settings → Graphics, выберите вкладку URP и не отмечайте флажок после Render Graph → Compatibility Mode (Render Graph Disabled).

Не отмечайте режим совместимости Render Graph

Не отмечайте режим совместимости Render Graph (Render Graph Disabled)

Отсечение окклюзией и настройка

Отсечение окклюзией должно включаться после настройки проектора. В примере сначала в обратном вызове завершения загрузки сцены вызывается SetDecalProjection, затем вызываются SetDecalOcclusionSettings и SetDecalOcclusion, чтобы карта глубины окклюзии получила валидную матрицу вида-проекции проектора. Во время выполнения включите флажок Occlusion в Inspector, чтобы увидеть, как проникающие блоки отсекаются и остаётся только передняя поверхность, обращённая к проектору.

Предпосылка:

Перед включением отсечения окклюзией Decal Depth Feature должен быть уже зарегистрирован в URP Renderer Asset (в этом проекте он записан в URP_Renderer.asset как субассет). Если он не зарегистрирован, карта глубины окклюзии не будет сгенерирована и окклюзия не вступит в силу.

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

ПараметрЭффектПо умолчаниюРекомендация по настройке
opacityCutoffОтфильтровывает плавающие / туманные сплаты, чтобы они не притягивали поверхность окклюзии ближе0Увеличивайте умеренно при появлении блочного шума на переднем плане; слишком большое значение вызывает пропуск окрашивания
depthBiasОтносительный допуск глубины, поглощающий толщину поверхности облака точек по расстоянию0.05Увеличивайте при появлении шума самоокклюзии на ближней поверхности; уменьшайте при утечке тонких окклюдеров
footprintMaxPxБлижняя глубина передней поверхности заполняет разреженные промежутки в мировом масштабе, главная ручка для исправления рентгеновского просвечивания2Увеличивайте, когда остаются проникающие блоки; уменьшайте при чрезмерной окклюзии контуров, 0 — один тексель
resolutionРазрешение карты глубины окклюзии1024Уменьшайте (например, 512 / 256), когда на скользящих поверхностях появляются большие участки пропущенного окрашивания мелких блоков, ценой чуть более грубых границ окклюзии

Ключевые шаги

Ключевые шаги для реализации проецируемой декали:

  1. Создайте пустой объект Projector в сцене в качестве проектора; его ось +Z — направление проекции.
  2. Если требуется отсечение окклюзией, убедитесь, что Decal Depth Feature добавлен в URP Renderer.
  3. После завершения загрузки LCC-сцены по порядку задайте текстуру декали, внешний вид и позу проектора, затем включите декаль (SetDecalEnabled(true)).
  4. Отсечение окклюзией SetDecalOcclusionSettings / SetDecalOcclusion должно вызываться после SetDecalProjection.

API, связанные с декалью

Следующие методы находятся в фасадном классе LCCManager и действуют только на PC / Mac (конвейер URP); вызовы на mobile / VR игнорируются, и выводится предупреждение.

SetDecalEnabled

// Возвращаемое значение: void
public void SetDecalEnabled(bool enable)

Переключает проекцию декали. При включении текущие кэшированные параметры непрозрачности / затухания края отправляются на GPU и активируется ключевое слово шейдера _DECAL. Декаль — это зафиксированное в мире глобальное состояние, согласованное для всех камер. Также необходимо вызвать SetDecalTexture и SetDecalProjection, чтобы задать содержимое и позу проектора.

ПараметрТипОписание
enableboolВключать ли проекцию декали

Пример использования:

m_manager.SetDecalEnabled(true);
m_manager.SetDecalTexture(decalTex);
m_manager.SetDecalProjection(projectorPos, projectorRot, 60f, 1.778f, 0.1f, 20f);

Примечания:

  • При выключении отключается только ключевое слово _DECAL; кэшированная текстура / параметры не очищаются.

SetDecalTexture

// Возвращаемое значение: void
public void SetDecalTexture(Texture2D tex)

Задаёт текстуру декали. RGB — цвет, а A — собственная маска декали, которая перемножается с глобальной непрозрачностью и затуханием края.

ПараметрТипОписание
texTexture2DТекстура декали

Пример использования:

m_manager.SetDecalTexture(logoTex);

Примечания:

  • Передача null очищает глобальную ссылку на текстуру.

SetDecalProjection

// Возвращаемое значение: void
public void SetDecalProjection(Vector3 pos, Quaternion rot, float fov, float aspect, float near, float far)

Задаёт позу проектора декали и параметры перспективы. Проектор проецирует вдоль своего переднего (+Z) направления, и точки внутри фрустума покрываются декалью.

ПараметрТипОписание
posVector3Мировая позиция проектора
rotQuaternionОриентация проектора
fovfloatВертикальный FOV (в градусах), ограничен [1, 179]
aspectfloatСоотношение сторон, минимум 1e-4
nearfloatБлижняя плоскость отсечения, минимум 1e-3
farfloatДальняя плоскость отсечения, минимум near + 1e-3

Пример использования:

m_manager.SetDecalProjection(new Vector3(0, 10, 0), Quaternion.Euler(90, 0, 0), 60f, 1.778f, 0.1f, 20f);

Примечания:

  • Если SetDecalOcclusion(true) уже включено, этот метод синхронно пересылает новую VP / вид в Decal Depth Feature.

SetDecalOpacity

// Возвращаемое значение: void
public void SetDecalOpacity(float opacity)

Задаёт общую непрозрачность декали, немедленно отправляя её на GPU и кэшируя для повторного использования при следующем вызове SetDecalEnabled(true).

ПараметрТипОписание
opacityfloatОбщая непрозрачность декали, диапазон [0, 1]

Пример использования:

m_manager.SetDecalOpacity(0.8f);

Примечания:

  • Диапазон [0, 1]; значения вне диапазона ограничиваются автоматически.

SetDecalEdgeFade

// Возвращаемое значение: void
public void SetDecalEdgeFade(float edgeFade)

Задаёт ширину затухания края декали. 0 — жёсткий край, чем больше значение, тем мягче переход края.

ПараметрТипОписание
edgeFadefloatШирина затухания края, отношение в пространстве UV, диапазон [0, 0.5)

Пример использования:

m_manager.SetDecalEdgeFade(0.1f);

Примечания:

  • Диапазон [0, 0.5); значения вне диапазона ограничиваются автоматически.

SetDecalOcclusion

// Возвращаемое значение: void
public void SetDecalOcclusion(bool enable)

Переключает отсечение окклюзией декали (на основе карты глубины проектора), которое ортогонально функции теней и переключается независимо. Перед включением должен быть вызван SetDecalProjection для настройки проектора, иначе у карты глубины нет валидной VP.

ПараметрТипОписание
enableboolВключать ли отсечение окклюзией декали

Пример использования:

m_manager.SetDecalOcclusion(true);

Примечания:

  • Поддерживается только на URP (вызовы на конвейере Built-in ничего не делают и выводят журнал).
  • Требует регистрации Decal Depth Feature в URP Renderer Asset.
  • Зависит от параметров качества, настроенных через SetDecalOcclusionSettings.

SetDecalOcclusionSettings

// Возвращаемое значение: void
public void SetDecalOcclusionSettings(DecalOcclusionSettings settings)

Задаёт все параметры качества отсечения окклюзией декали сразу (значения четырёх элементов см. в структуре ниже и таблице «Отсечение окклюзией и настройка»).

ПараметрТипОписание
settingsDecalOcclusionSettingsПараметры качества отсечения окклюзией

Пример использования:

m_manager.SetDecalOcclusionSettings(DecalOcclusionSettings.Default);
m_manager.SetDecalOcclusionSettings(new DecalOcclusionSettings {
    opacityCutoff = 0.1f,
    depthBias = 0.05f,
    footprintMaxPx = 2,
    resolution = 1024
});

Примечания:

  • Можно настраивать в любое время; параметры немедленно отправляются на GPU и в Decal Depth Feature.
  • Изменение resolution вызывает пересборку RT карты глубины.

Связанные структуры данных

DecalOcclusionSettings

public struct DecalOcclusionSettings {
    public float opacityCutoff;   // [0,1] минимальная непрозрачность для участия сплата в карте глубины, по умолчанию 0 (участвуют все)
    public float depthBias;       // относительный коэффициент допуска глубины, по умолчанию 0.05
    public int   footprintMaxPx;  // ограничение квадратного радиуса следа (px), 0~16, по умолчанию 2
    public int   resolution;      // разрешение карты глубины (px, степень двойки, 256~4096), по умолчанию 1024

    public static DecalOcclusionSettings Default { get; } // cutoff=0, bias=0.05, footprint=2, resolution=1024
}

Используется методом SetDecalOcclusionSettings(); значение по умолчанию можно получить через DecalOcclusionSettings.Default.

ПолеЗначениеПо умолчанию
opacityCutofffloat, [0,1], порог непрозрачности; только сплаты с непрозрачностью не ниже этого значения участвуют в карте глубины0
depthBiasfloat, относительный допуск глубины0.05
footprintMaxPxint, 0~16, ограничение квадратного радиуса следа (px)2
resolutionint, степень двойки 256~4096, разрешение карты глубины окклюзии1024

Примечания

  • Действует только на PC / Mac. Вызовы связанных с декалью интерфейсов на платформах mobile и VR игнорируются и выводят предупреждение. Вам не нужно выполнять проверки платформ на стороне бизнес-логики, но не ожидайте увидеть эффект на этих платформах.
  • Рекомендуется задавать декаль после завершения загрузки сцены. Декаль — глобальное состояние затенения; в примере SetDecalTexture / SetDecalProjection / SetDecalEnabled помещены в обратный вызов завершения Load, чтобы не задавать их до готовности облака точек.
  • Отсечение окклюзией зависит от двух предпосылок. Во-первых, в URP Renderer Asset зарегистрирован Decal Depth Feature; во-вторых, вызван SetDecalProjection для настройки проектора. Если отсутствует любая из них, окклюзия не вступает в силу.
  • Статическая проекция имеет почти нулевые дополнительные накладные расходы. Карта глубины окклюзии пересчитывается только при изменении позы проектора или облака точек; когда проектор неподвижен, дополнительных покадровых вычислений нет.