實時裁剪開發指南
LCC Unity SDK 支持對 3DGS 場景進行高亮、裁剪等編輯操作。本文介紹實時裁剪相關操作:通過 2D 投影紋理、3D 幾何體或二者混合的方式圈選區域,把選中區域從場景中裁掉,支持正選、反選等操作。
注意:
當前裁剪功能僅是運行時的顯示效果,不會對原始數據文件產生任何修改,也不支持將編輯結果保存導出。如果需要調色、裁剪並保存數據,請使用其域創新(XGrids)LCC Editor 軟件工具處理。
如果不希望修改數據,也可以將操作記錄下來,下次在數據加載完成後重放操作。
前置條件
通過 SDK 對場景進行裁剪,需要滿足以下條件:
- 在加載數據之前進入編輯狀態。 SDK 默認處於瀏覽狀態(View),該狀態能提供最佳性能,正常瀏覽時建議保持。要進行裁剪等編輯操作,需在
Load數據之前通過SetEditorMode(true)切換到編輯狀態。該方法只在加載所有數據之前調用才有效。 - 在數據加載完成後再執行裁剪操作。 裁剪接口需要在場景數據完全加載後調用。
步驟 1:搭建場景
參照下圖在場景中準備好裁剪所需的遊戲對象。

裁剪示例的場景層級結構
- Main Camera:場景相機,2D 裁剪會用到它的視圖與投影矩陣。
- LCCManager:空遊戲對象,Transform 歸一,添加
LCCManager腳本。 - LCCRenderer:空遊戲對象,Transform 設置為 Rotation.x = -90、Scale.x = -1(與 LCC 數據座標系對齊),用於掛載後面編寫的
Clip腳本。 - 3D 選區幾何體:用於 3D 裁剪的輔助對象。示例中準備了 3 個 Cube(
Box1、Box2、Box3)和 1 個 Sphere(Clipsphere),移動、縮放這些對象即可控制裁剪選區的位置和大小。
注意:
渲染相機、LCCManager、LCCRenderer 遊戲對象(GameObject)相關設置請參照PC 快速開發入門指南、工程設置優化指南 相關章節。

用於 3D 裁剪的選區幾何體(Box1 / Box2 / Box3 / Clipsphere)
步驟 2:了解數據結構
裁剪涉及 2D、3D 和 2D/3D 混合三種操作方式,用到的枚舉和結構體如下。
public enum SelectMode { normal, invert, clip } // 正常選區、反選、實時裁剪
public enum OperationMode { normal, erase } // 正常選區、擦除選區
public enum ShapeType { box, sphere } // 3D Box 選區、3D Sphere 選區
public enum EditType { Edit2D, Edit3D } // 2D 編輯、3D 編輯
// 2D 紋理選區
public struct Data2D
{
public Texture2D texture; // 2D 蒙版紋理
public Matrix4x4 mv; // 相機視圖矩陣
public Matrix4x4 mvp; // 相機視圖投影矩陣
public SelectMode mode; // 選擇模式
}
// 3D 幾何體選區
public struct Data3D
{
public ShapeType type; // 幾何體類型(box / sphere)
public Matrix4x4 invMat; // 幾何體的世界到局部(逆變換)矩陣
public OperationMode operation; // 操作類型(normal 並集 / erase 差集)
public SelectMode mode; // 選擇模式
}
// 2D / 3D 混合選區
public struct DataMix
{
public EditType editType; // 編輯類型(必填,決定使用 2D 還是 3D 字段)
public Texture2D texture; // 2D 蒙版紋理(Edit2D 使用)
public Matrix4x4 mv; // 相機視圖矩陣(Edit2D 使用)
public Matrix4x4 mvp; // 相機視圖投影矩陣(Edit2D 使用)
public ShapeType type; // 幾何體類型(Edit3D 使用)
public Matrix4x4 invMat; // 幾何體逆變換矩陣(Edit3D 使用)
public OperationMode operation; // 操作類型(Edit3D 使用)
public SelectMode mode; // 選擇模式(必填)
}
關於選區列表,有三點需要注意:
- 列表是有序的。 無論 2D 還是 3D,列表中的條目按順序依次生效,請確保添加順序符合預期。
- 反選是操作指令,可不關聯具體選區數據。 只需追加一個
mode = SelectMode.invert的條目,即可把已圈選區域反選。 - 單個列表的條目數量上限為 255。 超出會返回錯誤碼。
步驟 3:了解裁剪 API
裁剪相關接口都由 LCCManager 提供,包含三個 SetClip 重載和一個退出方法。
SetClip(2D 紋理裁剪)
// 返回值:int
// 0:執行成功
// 1:列表為 null 或元素個數為 0
// 2:列表元素超出最大值 255
public int SetClip(List<Data2D> _2Ds)
使用 2D 投影紋理蒙版對場景進行裁剪,被標記的區域從場景中裁掉。
SetClip(3D 幾何體裁剪)
// 返回值:int
// 0:執行成功
// 1:列表為 null 或元素個數為 0
// 2:列表元素超出最大值 255
// 3:用於選擇的幾何框數量為 0
public int SetClip(List<Data3D> _3Ds)
使用 3D 幾何體(長方體、正方體、球體)定義裁剪區域,支持並集與差集組合。至少需要一個 operation == OperationMode.normal 的幾何體。
SetClip(混合模式裁剪)
// 返回值:int
// 0:執行成功
// 1:列表為 null 或元素個數為 0
// 2:列表元素超出最大值 255
public int SetClip(List<DataMix> _Mix)
同時使用 2D 紋理和 3D 幾何體混合定義裁剪區域,每個條目通過 editType 決定按 2D 還是 3D 處理。
QuitClipMode
// 返回值:void
public void QuitClipMode()
退出裁剪模式,恢復場景完整顯示。
提示:
三個
SetClip重載互斥。切換裁剪方式或清除當前裁剪時,先調用QuitClipMode()再設置新的裁剪。
步驟 4:2D 蒙版紋理規範
2D 裁剪通過一張蒙版紋理來描述選區,可支持四邊形、三角形、筆刷、套索等各種圈選方式——在紋理上把對應像素標記為裁剪值即可。使用 2D 操作時應鎖定相機,在固定視角下標識紋理。紋理和像素值有如下約定:
- 紋理規格固定為 1024 × 1024,
R8單通道,不生成 Mipmap,使用點濾波(FilterMode.Point),採樣夾斷(TextureWrapMode.Clamp)。 - 像素值約定:
| 像素值 | 含義 |
|---|---|
128 | 默認(保留) |
240 | 選中 |
180 | 減選(擦除已選區域) |
0 | 裁剪 |
在裁剪場景下,通常只用到 128(默認保留)和 0(裁剪)兩個值。
步驟 5:編寫腳本
新建一個 C# 腳本,命名為 Clip.cs。先完成基礎框架:在 Start 中進入編輯狀態並加載數據,加載完成後置位加載標記,供後續裁剪方法判斷。
using LCCCore;
using System.Collections.Generic;
using UnityEngine;
public class Clip : MonoBehaviour
{
public LCCManager m_manager;
public string m_FilePath;
public GameObject m_Box1;
public GameObject m_Box2;
public GameObject m_Box3;
public GameObject m_Clipsphere;
private LCCCore.Renderer m_renderer;
private Camera m_camera;
private bool m_isLoaded = false;
void Start()
{
m_camera = Camera.main;
m_manager.SetPlatformType(PlatformType.PC);
// 進入編輯狀態,必須在 Load 之前調用
m_manager.SetEditorMode(true);
m_renderer = m_manager.GetRender(this.transform);
if (m_renderer == null)
Debug.LogError("GetRender failed, check if the manager is set correctly and the file path is valid.");
m_renderer.Load(m_FilePath, onLoadProgress, onLoadCallback);
}
private void onLoadProgress(float value)
{
Debug.Log($"loading progress: {value}");
}
private void onLoadCallback()
{
Debug.Log("data loaded !!!");
m_isLoaded = true;
// 關閉環境(遠景低精度點雲)渲染,便於觀察裁剪效果
m_renderer.SetEnvironment(false);
}
// 2D / 3D / 混合裁剪方法見下文
}
注意:
SetEditorMode(true)必須在Load之前調用才有效;而SetClip必須在數據加載完成(onLoadCallback回調觸發)之後調用。SetEnvironment(false)用於關閉遠景環境點雲,讓裁剪結果更清晰,可根據需要決定是否調用。
步驟 6:掛載腳本並設置屬性
- 將
Clip.cs腳本掛載到 LCCRenderer 遊戲對象上。 - 在 Inspector 窗口中,將 LCCManager 遊戲對象拖動到腳本的 Manager 屬性上。
- 在 File Path 屬性中填寫 LCC 文件的路徑地址。
- 將場景中的
Box1、Box2、Box3、Clipsphere分別拖動到腳本對應的屬性上。

在 Inspector 中設置 Clip 腳本的屬性
步驟 7:裁剪操作示例
將下面的方法補充到 Clip 類中,並在運行、數據加載完成後調用對應方法。
2D 紋理裁剪
構造兩張 R8 蒙版紋理,把要裁掉的像素標記為 0、其餘保留區域標記為 128,再用相機矩陣構造 Data2D 加入列表。
public void on2DClip()
{
// 紋理尺寸固定 1024*1024,其它屬性保持與示例一致
Texture2D _texture = new Texture2D(1024, 1024, TextureFormat.R8, false);
_texture.filterMode = FilterMode.Point;
_texture.wrapMode = TextureWrapMode.Clamp;
int _count = 1024 * 1024;
int _half = _count / 2;
byte[] _values = new byte[_count];
for (int i = 0; i < _count; i++)
{
if (i < _half)
_values[i] = 0; // 0 表示裁剪,128 表示默認,240 表示選中
else
_values[i] = 128;
}
_texture.SetPixelData(_values, 0);
Texture2D _texture2 = new Texture2D(1024, 1024, TextureFormat.R8, false);
_texture2.filterMode = FilterMode.Point;
_texture2.wrapMode = TextureWrapMode.Clamp;
byte[] _values2 = new byte[_count];
for (int i = 0; i < _count; i++)
{
if (i > _count * 0.75 && i < _count * 0.9)
_values2[i] = 0;
else
_values2[i] = 128;
}
_texture2.SetPixelData(_values2, 0);
List<Data2D> _2Ds = new List<Data2D>();
Data2D _2d01 = new Data2D();
_2d01.mv = m_camera.worldToCameraMatrix;
_2d01.texture = _texture;
_2d01.mode = SelectMode.normal;
_2d01.mvp = GL.GetGPUProjectionMatrix(m_camera.projectionMatrix, true) * m_camera.worldToCameraMatrix;
_2Ds.Add(_2d01);
Data2D _2d02 = new Data2D();
_2d02.mv = m_camera.worldToCameraMatrix;
_2d02.texture = _texture2;
_2d02.mode = SelectMode.normal;
_2d02.mvp = GL.GetGPUProjectionMatrix(m_camera.projectionMatrix, true) * m_camera.worldToCameraMatrix;
_2Ds.Add(_2d02);
m_manager.SetClip(_2Ds);
}
代碼解釋 : 構建了兩張紋理蒙板,第一張蒙板將屏幕下半區域裁掉(屏幕以左下角為原點),第二張蒙板將上半屏幕 0.75 到 0.9 的區域裁掉,示例效果如下。
在實際使用時,可使用矩形框、三角形、筆刷、套索等各種圈選工具對蒙板對應位置進行選擇。

2D 紋理裁剪效果
3D 幾何體裁剪
用幾何體的 worldToLocalMatrix 作為選區逆變換矩陣,通過 operation 組合並集(normal)與差集(erase),可通過 mode = SelectMode.invert 的條目實現反選。
public void on3DClip()
{
List<Data3D> _3Ds = new List<Data3D>();
var _mat1 = m_Box1.transform.worldToLocalMatrix;
var _mat2 = m_Box2.transform.worldToLocalMatrix;
var _mat3 = m_Box3.transform.worldToLocalMatrix;
var _mat4 = m_Clipsphere.transform.worldToLocalMatrix;
// Box 選區
Data3D _3d01 = new Data3D();
_3d01.type = ShapeType.box;
_3d01.operation = OperationMode.normal;
_3d01.mode = SelectMode.normal;
_3d01.invMat = _mat1;
_3Ds.Add(_3d01);
Data3D _3d02 = new Data3D();
_3d02.type = ShapeType.box;
_3d02.operation = OperationMode.normal;
_3d02.mode = SelectMode.normal;
_3d02.invMat = _mat2;
_3Ds.Add(_3d02);
// Sphere 選區
Data3D _3d04 = new Data3D();
_3d04.type = ShapeType.sphere;
_3d04.operation = OperationMode.normal;
_3d04.mode = SelectMode.normal;
_3d04.invMat = _mat4;
_3Ds.Add(_3d04);
// 擦除 Box/Sphere(差集)
Data3D _3d03 = new Data3D();
_3d03.type = ShapeType.box;
_3d03.operation = OperationMode.erase;
_3d03.mode = SelectMode.normal;
_3d03.invMat = _mat3;
_3Ds.Add(_3d03);
// 反選
//Data3D _3d05 = new Data3D();
//_3d05.mode = SelectMode.invert;
//_3Ds.Add(_3d05);
m_manager.SetClip(_3Ds);
}
代碼解釋 : 使用了 4 個幾何體,其中 Box1、Box2、Sphere 為正常選擇,而 Box3 為擦除選擇,即將之前已選中的區域進行擦除。註釋反選相關代碼,效果示例如下:

3D 幾何體裁剪效果
取消註釋反選代碼,即讓反選生效時,效果示例如下,反選即是將之前所選的選區反置,這是一條指令,可不與操作數據關聯。
特別需要注意的是,列表是有序的,不同的操作步驟會產生不同的最終效果。

3D 幾何體+反選裁剪效果
混合模式裁剪
在同一個列表中混用 2D 紋理和 3D 幾何體條目,每個條目通過 editType 指明處理方式。
public void onMixClip()
{
// --- 2D 選框準備 ---
// 紋理尺寸固定 1024*1024,其它屬性保持與示例一致
Texture2D _texture = new Texture2D(1024, 1024, TextureFormat.R8, false);
_texture.filterMode = FilterMode.Point;
_texture.wrapMode = TextureWrapMode.Clamp;
int _count = 1024 * 1024;
int _half = _count / 2;
byte[] _values = new byte[_count];
for (int i = 0; i < _count; i++)
{
if (i < _half)
_values[i] = 128; // 128 表示默認,240 表示選中,0 表示裁剪
else
_values[i] = 0;
}
_texture.SetPixelData(_values, 0);
List<DataMix> _Mixs = new List<DataMix>();
DataMix _mix01 = new DataMix();
_mix01.editType = EditType.Edit2D;
_mix01.mv = m_camera.worldToCameraMatrix;
_mix01.texture = _texture;
_mix01.mode = SelectMode.normal;
_mix01.mvp = GL.GetGPUProjectionMatrix(m_camera.projectionMatrix, true) * m_camera.worldToCameraMatrix;
_Mixs.Add(_mix01);
// --- 3D 選框準備 ---
var _mat1 = m_Box1.transform.worldToLocalMatrix;
var _mat2 = m_Box2.transform.worldToLocalMatrix;
var _mat3 = m_Box3.transform.worldToLocalMatrix;
var _mat4 = m_Clipsphere.transform.worldToLocalMatrix;
// Box 選區
DataMix _mix02 = new DataMix();
_mix02.editType = EditType.Edit3D;
_mix02.type = ShapeType.box;
_mix02.operation = OperationMode.normal;
_mix02.mode = SelectMode.normal;
_mix02.invMat = _mat1;
_Mixs.Add(_mix02);
DataMix _mix03 = new DataMix();
_mix03.editType = EditType.Edit3D;
_mix03.type = ShapeType.box;
_mix03.operation = OperationMode.normal;
_mix03.mode = SelectMode.normal;
_mix03.invMat = _mat2;
_Mixs.Add(_mix03);
// Sphere 選區
DataMix _mix04 = new DataMix();
_mix04.editType = EditType.Edit3D;
_mix04.type = ShapeType.sphere;
_mix04.operation = OperationMode.normal;
_mix04.mode = SelectMode.normal;
_mix04.invMat = _mat4;
_Mixs.Add(_mix04);
// 擦除 Box/Sphere(差集)
DataMix _mix05 = new DataMix();
_mix05.editType = EditType.Edit3D;
_mix05.type = ShapeType.box;
_mix05.operation = OperationMode.erase;
_mix05.mode = SelectMode.normal;
_mix05.invMat = _mat3;
_Mixs.Add(_mix05);
// 反選(按需啟用)
DataMix _mix06 = new DataMix();
_mix06.editType = EditType.Edit3D;
_mix06.type = ShapeType.box;
_mix06.mode = SelectMode.invert;
//_Mixs.Add(_mix06);
m_manager.SetClip(_Mixs);
}
代碼解釋 : 使用了 4 個幾何體和 1 張 2D 紋理,可 2D 與 3D 混合處理,效果示例如下:

混合模式裁剪效果
步驟 8:退出裁剪
調用 QuitClipMode() 即可清除當前裁剪,恢復場景完整顯示。
public void onClearClip()
{
m_manager.QuitClipMode();
}
關鍵步驟
對 3DGS 場景進行實時裁剪的關鍵步驟:
- 在
Load數據之前調用SetEditorMode(true)進入編輯狀態。 - 在數據加載完成後(
onLoadCallback回調觸發 或者通過按鈕/事件觸發)再調用SetClip。 - 根據需要選擇 2D 紋理、3D 幾何體或混合方式,並保證選區列表的添加順序符合預期。
- 2D 蒙版紋理固定為 1024 × 1024、
R8單通道,按約定填充像素值(128默認保留、0裁剪)。 - 需要清除或切換裁剪時,先調用
QuitClipMode()。