實時光照開發指南
LCC Unity SDK 支持動態點光源和聚光燈光源的實時光照。下面通過一個點光源繞圓周運動的示例,介紹實現實時光照的完整步驟。
步驟 1:創建場景與遊戲對象
在 Unity 中創建一個全新的場景,Unity 默認會創建 Main Camera 和 Directional Light。
設置 Main Camera
在 Hierarchy 窗口中選擇 Main Camera,在 Inspector 窗口中按下圖設置其屬性。

設置 Main Camera 的屬性
創建 LCCManager
在 Hierarchy 窗口空白處單擊鼠標右鍵,在彈出的菜單中選擇 Create Empty,創建一個空遊戲對象,命名為 LCCManager,將其 Transform 歸一,並通過 Add Component 為其添加 LCCManager 腳本。

創建 LCCManager 遊戲對象並添加 LCCManager 腳本
創建 LCCRenderer
在 Hierarchy 窗口空白處單擊鼠標右鍵,選擇 Create Empty,創建一個空遊戲對象,命名為 LCCRenderer,將其 Transform 設置為 Rotation.x = -90、Scale.x = -1。

創建 LCCRenderer 並設置 Transform(Rotation.x = -90、Scale.x = -1)
注意:
LCCRenderer 遊戲對象的 Transform 設置(Rotation.x = -90、Scale.x = -1)是與 LCC 數據座標系的對齊。關於座標系對齊的詳細說明,參見 Unity SDK 簡介 中的「LCC 數據座標系」。
步驟 2:編寫腳本下發光源
新建一個 C# 腳本,命名為 Relighting.cs,代碼如下:
using System.Collections.Generic;
using LCCCore;
using Unity.Mathematics;
using UnityEngine;
public class Relighting : MonoBehaviour
{
public LCCManager m_manager;
public string m_FilePath;
private LCCCore.Renderer m_renderer;
[Header("Point Light Settings")]
public Vector3 pointLightPosition = new Vector3(0, 2, 0);
public Color pointLightColor = Color.red;
public float pointLightIntensity = 2.0f;
public float pointLightRange = 3.0f;
[Header("Spot Light Settings")]
public Vector3 spotLightPosition = new Vector3(0, 2, -2);
public Vector3 spotLightDirection = new Vector3(0, -1, 0);
public Color spotLightColor = new Color(0.1f, 0.9f, 0.7f);
public float spotLightIntensity = 3.0f;
public float spotLightRange = 20.0f;
public float spotLightAngle = 45.0f;
[Header("Animation")]
public bool animateLights = true;
public float rotateSpeed = 30.0f;
private List<PointLightData> m_lights = new List<PointLightData>();
private float m_angle;
void Start()
{
m_manager.SetPlatformType(PlatformType.PC);
m_manager.SwitchRenderPass(ActiveRenderMode.SingleRender);
m_manager.SetMainCamera(Camera.main);
m_renderer = m_manager.GetRender(this.transform);
m_renderer.Load(m_FilePath, onProgress, onComplete);
}
private void onProgress(float _progress)
{
Debug.Log($"[Relighting] load progress: {_progress:P1}");
}
private void onComplete()
{
Debug.Log("[Relighting] load complete, setting up lights");
//m_manager.SetLightIntensity(0.5f);
ApplyLights();
}
void Update()
{
if (!animateLights) return;
m_angle += rotateSpeed * Time.deltaTime;
ApplyLights();
}
private void ApplyLights()
{
m_lights.Clear();
float rad = m_angle * Mathf.Deg2Rad;
float px = pointLightPosition.x + Mathf.Cos(rad) * 3f;
float pz = pointLightPosition.z + Mathf.Sin(rad) * 3f;
// lightType 0 = 點光源
m_lights.Add(new PointLightData
{
position = new float3(px, pointLightPosition.y, pz),
lightType = 0,
color = new float3(pointLightColor.r, pointLightColor.g, pointLightColor.b),
intensity = pointLightIntensity,
direction = float3.zero,
range = pointLightRange,
spotAngle = 0f,
pad = float3.zero
});
// lightType 1 = 聚光燈
Vector3 dir = spotLightDirection.normalized;
m_lights.Add(new PointLightData
{
position = new float3(spotLightPosition.x, spotLightPosition.y, spotLightPosition.z),
lightType = 1,
color = new float3(spotLightColor.r, spotLightColor.g, spotLightColor.b),
intensity = spotLightIntensity,
direction = new float3(dir.x, dir.y, dir.z),
range = spotLightRange,
spotAngle = spotLightAngle,
pad = float3.zero
});
int result = m_manager.SetLights(m_lights);
if (result != 0)
Debug.LogWarning($"[Relighting] SetLights failed: {result}");
}
void OnDisable()
{
// 傳入 null 關閉自定義光照
m_manager.SetLights(null);
}
}
注意:
- 實時光照需要在 LCC 場景加載完成後下發,因此首次
ApplyLights()在onComplete回調中調用。- 本示例在
Update中每幀刷新光源位置,實現點光源繞圓周運動的動畫效果。- 光源字段類型為
Unity.Mathematics.float3,需要using Unity.Mathematics;;color只有 RGB 三個分量,沒有 alpha。
步驟 3:掛載腳本並設置數據路徑
- 將
Relighting.cs腳本掛載到 Hierarchy 窗口中的 LCCManager 遊戲對象上。 - 在 Inspector 窗口中,將 LCCManager 遊戲對象拖動到腳本的 Manager 屬性上。
- 在腳本的 File Path 屬性中填寫 LCC 文件的路徑地址。
- 其餘點光源、聚光燈、動畫相關的屬性可自由設置。

掛載 Relighting 腳本並在 Inspector 中設置屬性
在本示例中,創建了一個點光源和一個聚光燈光源,並讓點光源繞圓周運動,用於演示實時光照效果。
步驟 4:運行
在 Game 窗口中點擊 Play 按鈕,即可看到場景中的實時光照效果。

運行後 3DGS 場景中的實時光照效果
3DGS 光照的特殊性
3DGS 中的光照相比於傳統 Mesh 模型光照有較大的不同。3DGS 的光照效果是直接寫入到 RGB 顏色中的,即光照部分固化到了渲染顏色分量中。因此,如果 3DGS 模型是在大太陽晴天採集、帶有非常強烈的硬陰影,重打光也無法消除這些已經固化的陰影。
另外,渲染時顏色取值範圍為 [0, 1]。如果不做處理直接增強光照,會出現過曝現象。為防止過曝,通常會將 3DGS 場景先壓暗一點再重打光。
在 SDK 中可通過 LCCManager.SetLightIntensity(float _intensity) 方法調整光照強度:
- 輸入參數
_intensity取值範圍為[0, 1]。 - 該函數影響整體光照效果:設置的光照強度越強,3DGS 場景會被壓得越暗。
- 默認值為
0.5。
提示:
光照計算是相對消耗性能的操作。SDK 最大支持 50 個動態光源(點光源和聚光燈光源合計)。超出上限時
SetLights會返回-1且不生效。
關鍵步驟
為 3DGS 場景添加實時光照的關鍵步驟:
- 完成
SetPlatformType/SwitchRenderPass/SetMainCamera等前置配置,並通過GetRender+Load加載 LCC 場景。 - 在場景加載完成後(
onComplete回調中)構建PointLightData列表並調用SetLights下發光源。 - 需要動畫時,在
Update中更新光源參數並重新調用SetLights。 - 如出現過曝,通過
SetLightIntensity先將場景壓暗再重打光。 - 關閉實時光照時,向
SetLights傳入null或空列表。
實時光照相關 API
LCC Unity SDK 通過 LCCManager 提供了以下兩個實時光照相關 API。它們都需要在 LCC 場景加載完成後調用(即在 onComplete 回調中)。
SetLights
// 返回值:int → 0=成功, -1=超出最大數量限制
public int SetLights(List<PointLightData> lights)
設置自定義點光源列表。傳入 null 或空列表可關閉自定義光照。
| 參數 | 類型 | 說明 |
|---|---|---|
lights | List<PointLightData> | 光源列表(點光源與聚光燈合計最多 50 個) |
調用示例:
using Unity.Mathematics; // float3
var lights = new List<PointLightData>();
lights.Add(new PointLightData {
position = new float3(0, 5, 0),
lightType = 0, // 0=點光源, 1=聚光燈
color = new float3(1, 1, 1),
intensity = 2f,
range = 10f
});
m_manager.SetLights(lights);
說明:
- 字段類型為
Unity.Mathematics.float3,非Vector4;color無 alpha 分量。 lightType:0= 點光源(忽略direction/spotAngle),1= 聚光燈(需設置direction/spotAngle)。- 最大數量為 50(點光源與聚光燈合計),超出返回
-1。 - 傳入
null或空列表關閉自定義光照。 - 開啟後會啟用
_USERLIGHTshader keyword。 - 數據結構定名為 PointLightData 原因是 UnityEngine 已定義 LightData ,為避免歧義。
SetLightIntensity
// 返回值:void
public void SetLightIntensity(float intensity)
設置全局光照強度,用於在重打光前壓暗 3DGS 場景、防止過曝。
| 參數 | 類型 | 說明 |
|---|---|---|
intensity | float | 光照強度,取值範圍 [0, 1] |
調用示例:
m_manager.SetLightIntensity(0.5f);
說明:
- 默認值為
0.5。 - 取值範圍
[0, 1],超出範圍會自動鉗制。 - 值越大,3DGS 場景整體被壓得越暗。
PointLightData 數據結構
public struct PointLightData {
public float3 position; // 世界座標
public int lightType; // 0=點光源, 1=聚光燈
public float3 color; // rgb 顏色(無 alpha 分量)
public float intensity; // 光照強度
public float3 direction; // 聚光燈朝向(點光源忽略)
public float range; // 光照範圍
public float spotAngle; // 聚光燈錐角(度,點光源忽略)
public float3 pad; // 對齊填充,無需賦值
}
| 字段 | 類型 | 說明 |
|---|---|---|
position | float3 | 光源世界座標 |
lightType | int | 0 = 點光源,1 = 聚光燈 |
color | float3 | RGB 顏色(無 alpha 分量) |
intensity | float | 光照強度 |
direction | float3 | 聚光燈朝向,點光源忽略 |
range | float | 光照範圍 |
spotAngle | float | 聚光燈錐角(度),點光源忽略 |
pad | float3 | 對齊填充,無需賦值 |