XGRIDS文档
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • 灵视 P 系列

    • 灵视 P1

      • 产品概述
      • 设备基本操作
      • 使用 LCC Scan App
      • 维护及保养
      • 常见问题
  • 灵光 K 系列

    • 灵光 K1

      • 产品概述
      • 设备基本操作
      • 设备激活与连接
      • 设备采集
      • 获取绝对坐标点云数据
      • 地图融合
      • 典型场景路线规划建议
      • 注意事项
      • 常见问题
    • 灵光 K2

      • 产品概述
      • 设备基本操作
      • 设备激活与连接
      • 设备采集
      • 获取绝对坐标点云数据
      • 地图融合
      • 典型场景路线规划建议
      • 注意事项
      • 常见问题
  • 灵光 L 系列

    • 灵光 L2 Pro

      • 产品概述
      • 设备基本操作
      • 设备激活与连接
      • 设备采集
      • 获取绝对坐标点云数据
      • 实时测量功能
      • 附录
      • 常见问题
    • 灵光 L3

      • 产品概述
      • 设备基本功能
      • 设备激活与连接
      • 设备采集
      • 获取绝对坐标点云数据操作流程
      • 附录
  • 配件

    • 补光灯

      • 安装指导
      • 基本操作
      • 常见问题
  • Lixel Studio

    • 版权
    • 安装与激活
    • 界面说明
    • 文件
    • 工程处理
    • 工具
    • 平面绘制
    • 行业应用
    • 设置
    • 设备感知
    • 常见问题 / FAQ
  • Lixel CyberColor

    • LCC Studio

      • 入门
      • 版本与更新
      • 下载与安装
      • 界面概览与导航
      • 重建前工作
      • 模型重建
      • 单模型重建
      • 地图融合
      • 空地融合
      • 航拍重建
      • 我的模型
      • 其他功能
      • 设置与账号
      • 转换工具
      • 视频重建
      • 常见问题 / FAQ
    • LCC Scene Editor

      • 版本与更新
      • 账号与登录
      • 产品概览与主页
      • 编辑器界面介绍
      • 三种场景漫游快捷操作
      • 文件
      • 设置
      • 编辑操作
      • 窗口
      • 视图工具栏
      • 资产与属性
      • 左侧工具栏
      • 视点
      • 跳转点
      • 天空盒
      • 标注
      • 测量
      • 场景漫游
      • 场景报告
      • 智能户型图(3D Layout)
      • 小地图
      • 预览模式(Viewer)
      • 帮助
      • 常见问题 / FAQ
      • 出生点
    • LCC Model Editor

      • 版本与更新
      • 新手指引
      • 概览与界面
      • 文件操作
      • 选择器
      • 编辑操作
      • 测量
      • 调色
      • 资产管理
      • 设置与帮助
      • 常见问题 / FAQ
    • 采集指南

      • 概述
      • 采集设备总览
      • 通用采集原则
      • 室内场景采集
      • 室外场景采集
      • 大场景采集(地图融合)
      • 空地融合采集
      • 物体采集
      • 人物采集
      • 视频重建采集
      • 高清补拍
      • 控制点(灵视 P1)
      • 常见问题与排查
    • LCC Studio Linux

      • 产品概要说明
      • 基本架构说明书
      • 安装部署说明书
      • 容器启动参数说明书
      • CodeMeter离线授权部署说明书
      • API指令集说明书
      • 附录-开发者数据说明书
      • 附录-错误码列表
      • 单机多卡集群部署QuickStart
    • 使用技巧

      • 多个大型 3DGS 模型融合工作流
    • 历史版本
  • Plugin & SDK

    • Unreal

      • 介绍
      • 快速入门 - Windows
      • 快速入门 - Linux
      • 快速入门 - Quest3
      • 版本与授权
      • 渲染
      • Tiled 光栅化(实验性)
      • 画面调节
      • 法线与光照
      • 场景编辑
      • 性能参数说明
      • 性能优化指南
      • 第三方与引擎插件集成
      • 代理网格
      • 加载动画
      • 碰撞
      • 寻路系统支持
      • 单层水支持
      • 本地化
      • 常见问题
      • 故障排查
      • 日志与诊断
      • 联系我们
      • 最佳实践

        • 用 LixelStudio 网格为 3DGS 重打光
      • API 参考

        • ALCCActorBase
        • ULCCComponentBase
        • ULCCComponent
        • ULCC2Component
        • SOG / SPZ / PLY Actors
        • 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 企业串流指南
      • 术语表
      • 常见问题
      • 联系我们
      • 功能开发指南

        • 多场景混合渲染开发指南
        • 阴影接收开发指南
        • 实时光照开发指南
        • 多相机渲染开发指南
        • 高清图像渲染开发指南
        • LCC 与 LCC2 数据格式兼容开发指南
        • 加载特效开发指南
        • Mip 渲染模式切换开发指南
        • 边角点吸附开发指南
        • 投影贴花开发指南
        • 视频流投影开发指南
        • 高亮显示开发指南
        • 实时裁剪开发指南
        • 调色开发指南
        • 获取场景 Mesh 数据开发指南
        • 编辑器模式开发指南
        • 渲染性能参数设置指南
        • 应用与数据协同打包开发指南
        • 碰撞系统开发指南
        • macOS 开发权限问题操作指南
        • iOS 设备编译打包开发指南
      • API 参考

        • LCCManager
        • Renderer
        • 数据类型
      • 更新日志

        • v2.3.0
        • v2.2.10
        • v2.2.0
        • v2.1.19
        • v2.0.14
    • X-Brain

      • 产品概述
      • 硬件接口
      • 快速开始
      • 核心概念
      • 集成指南
      • API 参考
      • 数据类型
      • ROS2 桥接
      • 示例程序
      • 部署与网络
      • 排障与 FAQ
      • 版本与发布
    • Web

      • 介绍
      • 渲染性能优化指南
      • 显卡配置
      • 常见开发问题
      • API参考

        • LCCRender::clearIndexDB
        • LCCRender::dispose
        • LCCRender::load
        • LCCRender::setCamera
        • LCCRender::unload
        • LCCRender::update
        • LCCObject::checkRenderNextFrame
        • LCCObject::clearRenderNextFrame
        • LCCObject::ecef2Prj
        • LCCObject::getBounds
        • LCCObject::getEnvInstancedMesh
        • LCCObject::getInstancedMesh
        • LCCObject::getLodInfos
        • LCCObject::getOriginPosition
        • LCCObject::getProjectionCoordinateSystemInfos
        • LCCObject::hasCollision
        • LCCObject::hasEnvironment
        • LCCObject::hasShcoef
        • LCCObject::intersectsCapsule
        • LCCObject::intersectsRayExt
        • LCCObject::intersectsRayFromOriginExt
        • LCCObject::intersectsSphere
        • LCCObject::lowerToBottom
        • LCCObject::prj2Ecef
        • LCCObject::raiseToTop
        • LCCObject::raycast
        • LCCObject::raycastFromOrigin
        • LCCObject::setAlpha
        • LCCObject::setClipBox
        • LCCObject::setClipPlane
        • LCCObject::setEndLod
        • LCCObject::setLodAutoLevelUp
        • LCCObject::setMaxDistance
        • LCCObject::setMaxNodeSplats
        • LCCObject::setMaxSplats
        • LCCObject::setOriginPosition
        • LCCObject::setPointsColor
        • LCCObject::setRenderState
        • LCCObject::setRotation
        • LCCObject::setScale
        • LCCObject::setSemantic
        • LCCObject::setSemanticColor
        • LCCObject::setSmooth
        • LCCObject::setStartLod
        • LCCObject::setTranslation
        • LCCObject::setVisible
        • LCCObject::togglePointsDisplayMode
        • LCCObject::useEnvironment
        • LCCObject::useShcoef
      • 更新日志

        • v0.6.3
        • v0.6.2
        • v0.6.1
        • v0.6.0
        • v0.5.5
        • v0.5.4
        • v0.5.3
        • v0.5.2
        • v0.5.1
        • v0.5.0
        • v0.4.1
        • v0.4.0
        • v0.3.1
        • v0.3.0
        • v0.2.0
    • Lixel OpenAPI

      • 概述
      • 连接与鉴权
      • 消息模型与编解码
      • 接口清单
      • 实时数据
      • 项目文件访问
      • 错误码
      • Python

        • 快速开始
        • 客户端封装与工具
        • 常见问题
      • C++

        • 快速开始
        • 客户端与示例
        • 常见问题

投影贴花开发指南

功能概述

贴花投影(Decal Projector)把一张 2D 图片像幻灯机一样投射到 3DGS 点云表面。投影仪是世界空间中一个固定的透视视锥,落在视锥内的点云被贴花颜色覆盖,视锥外的点云不受影响。贴花是全局着色状态,对整个 3DGS 场景具有一致的着色效果。

在基础投影之上可选开启遮挡剔除。默认贴花是 X 光式的:由于 3DGS 本身并没有表面的概念,贴花会穿透打到被前方物体遮挡的背面,并穿透整个 3DGS 场景;开启遮挡剔除后,只有正对投影仪的前表面被染色,被挡住的背面与被遮场景不再染色,从而得到真实的幻灯机效果。

说明:

贴花与遮挡剔除仅在 PC / Mac(URP 管线) 下生效。在移动端或 VR 平台调用相关接口会被 SDK 忽略,并打印一条警告日志。无需在业务侧做平台判断,但也不要期望在这些平台看到效果。

步骤 1:创建场景与游戏对象

在 Unity 中创建一个全新的场景,Unity 默认会创建 Main Camera 和 Directional Light。

设置 Main Camera

在 Hierarchy 窗口中选择 Main Camera,在 Inspector 窗口中按下图设置其属性。

设置 Main Camera 的属性

设置 Main Camera 的属性

创建 LCCManager

在 Hierarchy 窗口空白处单击鼠标右键,在弹出的菜单中选择 Create Empty,创建一个空游戏对象,命名为 LCCManager,将其 Transform 归一,并通过 Add Component 为其添加 LCCManager 脚本。

创建 LCCManager 游戏对象并添加 LCCManager 脚本

创建 LCCManager 游戏对象并添加 LCCManager 脚本

创建 LCCRenderer

在 Hierarchy 窗口空白处单击鼠标右键,选择 Create Empty,创建一个空游戏对象,命名为 LCCRenderer,将其 Transform 设置为 Rotation.x = -90、Scale.x = -1。

创建 LCCRenderer 并设置 Transform

创建 LCCRenderer 并设置 Transform(Rotation.x = -90、Scale.x = -1)

注意:

LCCRenderer 游戏对象的 Transform 设置(Rotation.x = -90、Scale.x = -1)是与 LCC 数据坐标系的对齐。关于坐标系对齐的详细说明,参见 Unity SDK 简介 中的「LCC 数据坐标系」。

创建 Projector

在 Hierarchy 窗口空白处单击鼠标右键,选择 Create Empty,创建一个空游戏对象,命名为 Projector。创建该空对象的目的是使用其 Transform 组件来控制投影仪的位置、方向等属性;将其关联到脚本代码后,可在运行时调整投影仪属性。投影仪沿其 +Z 方向投影,其属性可根据需要设置。

创建 Projector 空游戏对象作为投影仪

创建 Projector 空游戏对象作为投影仪(+Z 为投影方向)

步骤 2:添加 Render Feature

  1. 在 Unity 菜单栏中选择 File → Project Settings,在左侧选择 Graphics,确认当前使用的 Default Render Pipeline Asset。本示例为 URP(Universal Render Pipeline Asset)。
在 Graphics 设置中确认 Default Render Pipeline Asset

在 Graphics 设置中确认 Default Render Pipeline Asset

  1. 点击该 Asset,在 Project 窗口中定位到对应的资源文件,找到与之关联的 Renderer(本示例为 URP_Renderer.asset)。

  2. 选中该 Renderer 资源文件,在 Inspector 窗口中点击 Add Renderer Feature,添加 Decal Depth Feature。

在 URP Renderer 中添加 Decal Depth Feature

在 URP Renderer 中添加 Decal Depth Feature

注意:

Decal Depth Feature 是遮挡剔除的前提。若只使用基础投影(X 光式贴花),可不添加;但要开启遮挡剔除,则必须先在 URP Renderer Asset 中注册该 Feature,否则遮挡深度图不会生成,遮挡不生效。

步骤 3:编写脚本

新建一个 C# 脚本,命名为 Decal.cs。下面的完整代码模拟接入方视角,覆盖全部 7 个贴花相关方法(5 个基础投影 + 2 个遮挡剔除),可直接复制到工程使用。

using LCCCore;
using UnityEngine;

/// <summary>
/// Decal 贴花投影 —— 开发者最小使用示例。
///
/// 本脚本模拟"接入方脚本",只调用 LCCManager 的 public API,不触碰 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)生效,移动端/VR 调用会被 SDK 忽略并打印 LogWarning。
/// </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("开启后被前方遮挡的背面/被挡点云不再被贴花染色(幻灯机效果),关闭则 X 光穿透")]
    public bool m_occlusion = false;
    [Range(0f, 1f)][Tooltip("opacity 阈值: 仅 opacity ≥ 此值的 splat 参与深度图,滤浮点/雾状点。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, 2 的幂 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 keyword)

        // ── 遮挡剔除:2 个 API ── 必须在 ApplyProjection 之后(深度图需有效投影仪 VP)
        m_manager.SetDecalOcclusionSettings(BuildOcclusionSettings());
        m_manager.SetDecalOcclusion(m_occlusion);
        CacheOcclusionState();

        m_loaded = true;
    }

    /// <summary>
    /// 仅演示使用,实际项目中,为提高性能,不需要在 Update() 方法中每帧调用
    /// SetDecalProjection / SetDecalOpacity / SetDecalEdgeFade 等,仅在参数变化时调用相应 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("Decal On")]  private void DecalOn()  { m_manager?.SetDecalEnabled(true); }
    [ContextMenu("Decal Off")] private void DecalOff() { m_manager?.SetDecalEnabled(false); }
    [ContextMenu("Occlusion On")]  private void OcclusionOn()  { m_occlusion = true;  m_manager?.SetDecalOcclusion(true);  m_lastOcclusion = true; }
    [ContextMenu("Occlusion Off")] 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 脚本挂载到 Hierarchy 窗口中的 LCCRenderer 游戏对象上。
  2. 在 Inspector 窗口中,将 LCCManager 游戏对象拖动到脚本的 Manager 属性上。
  3. 将 Projector 游戏对象拖动到脚本的 Projector 属性上。
  4. 在脚本的 File Path 属性中填写 LCC 文件的路径地址,并将贴花纹理图片拖到 Decal Texture 属性上。
  5. 其他属性参数可根据需要调整,各属性含义见下表。
Decal 脚本的 Inspector 属性设置

Decal 脚本的 Inspector 属性设置

字段含义默认值
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 Cutoffopacity 阈值,仅 opacity 不低于该值的 splat 参与深度图0
Occlusion Bias相对深度容差0.05
Occlusion Footprint方形足迹半径上限(px),去穿透漏染主旋钮2
Occlusion Resolution遮挡深度图分辨率(px,2 的幂 256~4096)1024

步骤 5:运行效果

在 Unity 中点击 Play 按钮,场景加载完成后贴花会自动开启。当勾选 Update Every Frame 时,运行过程中可直接在 Scene 视图拖动投影仪对象,实时看到贴花在 3DGS 表面移动;调整 Opacity、Edge Fade 等参数也会即时生效。脚本组件的右键菜单还提供 Decal On/Off、Occlusion On/Off 四个快捷入口,便于单独验证开关效果。

运行后贴花投影到 3DGS 表面(基础投影)

运行后贴花投影到 3DGS 表面(基础投影,X 光式穿透)

开启遮挡剔除后只有正对投影仪的前表面被染色

开启遮挡剔除后,只有正对投影仪的前表面被染色(幻灯机效果)

常见问题:关闭兼容模式

如果 Unity Console 窗口报错且没有出现贴花效果,请关闭兼容模式:通过 Edit → Project Settings → Graphics 打开设置面板,选择 URP 选项卡,不要勾选 Render Graph → Compatibility Mode (Render Graph Disabled) 后的多选框。

不要勾选 Render Graph 兼容模式

不要勾选 Render Graph 兼容模式(Render Graph Disabled)

遮挡剔除与调参

遮挡剔除需在设置好投影仪之后再开启。示例在场景加载完成回调里先调用 SetDecalProjection,再调用 SetDecalOcclusionSettings 与 SetDecalOcclusion,以保证遮挡深度图拿到有效的投影仪视图投影矩阵。运行时把 Inspector 的 Occlusion 勾选打开,即可看到穿透块被剔除、只保留正对投影仪的前表面。

前提:

开启遮挡剔除前,URP Renderer Asset 中必须已注册 Decal Depth Feature(本工程已作为子资源写入 URP_Renderer.asset)。若未注册,遮挡深度图不会生成,遮挡不会生效。

遮挡质量由四个参数控制,通过一个结构体一次性下发。四者相互正交,按下表调节:

参数作用默认调节建议
opacityCutoff过滤漂浮 / 雾状 splat,避免它们把遮挡面拉近0前景出现块状噪点时适度调大;调太大会漏染
depthBias相对深度容差,按距离吸收点云表面厚度0.05近面出现自遮挡噪点时调大;薄遮挡物漏挡时调小
footprintMaxPx前表面近深度按世界尺度盖满稀疏缝隙,根治穿透漏染(主旋钮)2穿透块残留时调大;轮廓过遮挡时调小,0 为单纹素
resolution遮挡深度图分辨率1024掠射面出现成片漏染小方块时调低(如 512 / 256),代价是遮挡边界略糙

关键步骤

实现投影贴花的关键步骤:

  1. 场景中创建 Projector 空对象作为投影仪,其 +Z 朝向即投影方向。
  2. 若需要遮挡剔除,确保在 URP Renderer 中添加了 Decal Depth Feature 渲染特性。
  3. 在 LCC 场景加载完成后依次设置贴花纹理、外观、投影仪位姿,再开启贴花(SetDecalEnabled(true))。
  4. 遮挡剔除的 SetDecalOcclusionSettings / SetDecalOcclusion 需在 SetDecalProjection 之后调用。

贴花相关 API

以下方法均位于 LCCManager 门面类,仅 PC / Mac(URP 管线)生效,移动端 / VR 调用会被忽略并打印警告。

SetDecalEnabled

// 返回值:void
public void SetDecalEnabled(bool enable)

开关贴花投影。开启时会把当前缓存的不透明度 / 边缘羽化参数推到 GPU 并启用 _DECAL shader keyword。贴花是世界固定的全局状态,对所有相机一致。需另外调用 SetDecalTexture 与 SetDecalProjection 设置内容与投影仪位姿。

参数类型说明
enablebool是否开启贴花投影

调用示例:

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

说明:

  • 关闭时仅禁用 _DECAL keyword,不清空已缓存的纹理 / 参数。

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)

设置贴花投影仪的位姿与透视参数,投影仪沿其 forward(+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 / view 转发给 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 支持(内置管线调用直接 no-op 并打印日志)。
  • 需要 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] splat 参与深度图的最低 opacity,默认 0(全部参与)
    public float depthBias;       // 相对深度容差比例,默认 0.05
    public int   footprintMaxPx;  // 方形足迹半径上限(px),0~16,默认 2
    public int   resolution;      // 深度图分辨率(px,2 的幂,256~4096),默认 1024

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

用于 SetDecalOcclusionSettings(),可通过 DecalOcclusionSettings.Default 获取默认值。

字段含义默认
opacityCutofffloat,[0,1],opacity 阈值,仅不低于该值的 splat 参与深度图0
depthBiasfloat,相对深度容差0.05
footprintMaxPxint,0~16,方形足迹半径上限(px)2
resolutionint,2 的幂 256~4096,遮挡深度图分辨率1024

注意事项

  • 仅 PC / Mac 生效。 移动端与 VR 平台调用贴花相关接口会被忽略并打印警告,无需在业务侧做平台判断,但也不要期望在这些平台看到效果。
  • 建议在场景加载完成后再设置贴花。 贴花是全局着色状态,示例把 SetDecalTexture / SetDecalProjection / SetDecalEnabled 放在 Load 完成回调里,避免点云尚未就绪时设置。
  • 遮挡剔除依赖两个前提。 一是 URP Renderer Asset 已注册 Decal Depth Feature,二是已调用过 SetDecalProjection 设定投影仪;两者缺一则遮挡不生效。
  • 静态投影几乎零额外开销。 遮挡深度图仅在投影仪位姿或点云发生变化时重算,投影仪静止时不产生额外的每帧计算。