リアルタイムライティング開発ガイド
LCC Unity SDK は、動的な ポイントライト と スポットライト によるリアルタイムライティングに対応しています。以下では、円形パスに沿って移動するポイントライトの例を使って、リアルタイムライティングを実装する完全な手順を説明します。
手順 1:シーンと GameObject を作成する
Unity で新しいシーンを作成します。Unity はデフォルトで Main Camera と Directional Light を作成します。
Main Camera をセットアップする
Hierarchy ウィンドウで Main Camera を選択し、Inspector ウィンドウでそのプロパティを以下のとおり設定します。

Main Camera のプロパティを設定
LCCManager を作成する
Hierarchy ウィンドウの空の領域を右クリックし、ポップアップメニューから Create Empty を選択して空の GameObject を作成し、LCCManager と名前を付け、その Transform を正規化し、Add Component で LCCManager スクリプトを追加します。

LCCManager GameObject を作成し LCCManager スクリプトを追加
LCCRenderer を作成する
Hierarchy ウィンドウの空の領域を右クリックし、Create Empty を選択して空の GameObject を作成し、LCCRenderer と名前を付け、その Transform を Rotation.x = -90、Scale.x = -1 に設定します。

LCCRenderer を作成し Transform(Rotation.x = -90、Scale.x = -1)を設定
注:
LCCRenderer GameObject の Transform 設定(Rotation.x = -90、Scale.x = -1)は、LCC データ座標系にアライメントするためのものです。座標系アライメントの詳細は Unity SDK の概要 の「LCC データの座標系」を参照してください。
手順 2:ライトを送信するスクリプトを書く
Relighting.cs という名前の新しい C# スクリプトを以下のコードで作成します。
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("ポイントライト設定")]
public Vector3 pointLightPosition = new Vector3(0, 2, 0);
public Color pointLightColor = Color.red;
public float pointLightIntensity = 2.0f;
public float pointLightRange = 3.0f;
[Header("スポットライト設定")]
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("アニメーション")]
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] 読み込み進捗: {_progress:P1}");
}
private void onComplete()
{
Debug.Log("[Relighting] 読み込み完了、ライトを設定中");
//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 に失敗しました: {result}");
}
void OnDisable()
{
// カスタムライティングを無効にするには null を渡す
m_manager.SetLights(null);
}
}
注:
- リアルタイムライティングは LCC シーンの読み込み完了後 に送信する必要があるため、最初の
ApplyLights()はonCompleteコールバックで呼び出します。- この例では
Updateで毎フレームライト位置を更新し、円形パスに沿って移動するポイントライトをアニメーションさせます。- ライトフィールドの型は
Unity.Mathematics.float3で、using Unity.Mathematics;が必要です。colorは RGB 3 成分のみで、アルファはありません。
手順 3:スクリプトをアタッチしてデータパスを設定する
Relighting.csスクリプトを Hierarchy ウィンドウの LCCManager GameObject にアタッチします。- Inspector ウィンドウで LCCManager GameObject をスクリプトの Manager プロパティへドラッグします。
- スクリプトの File Path プロパティに LCC ファイルパスを入力します。
- 残りのポイントライト、スポットライト、アニメーションのプロパティは自由に設定できます。

Relighting スクリプトをアタッチして Inspector でプロパティを設定
この例では、ポイントライト 1 つとスポットライト 1 つを作成し、ポイントライトが円形パスに沿って移動してリアルタイムライティング効果を実演します。
手順 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 を通じて以下の 2 つのリアルタイムライティング 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にはアルファ成分がありません。 lightType:0= ポイントライト(direction/spotAngleは無視)、1= スポットライト(direction/spotAngleが必要)。- 最大数は 50(ポイントライトとスポットライトの合計)。超えると
-1を返します。 nullまたは空リストを渡すとカスタムライティングが無効になります。- 有効にすると、
_USERLIGHTシェーダーキーワードが有効になります。 - UnityEngine が既に LightData を定義しているため、曖昧さを避けるためにデータ構造の名前は PointLightData になっています。
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 カラー(アルファ成分なし)
public float intensity; // ライト強度
public float3 direction; // スポットライトの方向(ポイントライトでは無視)
public float range; // ライトの範囲
public float spotAngle; // スポットライトのコーン角度(度、ポイントライトでは無視)
public float3 pad; // アライメントパディング。代入不要
}
| フィールド | 型 | 説明 |
|---|---|---|
position | float3 | ライトのワールド座標 |
lightType | int | 0 = ポイントライト、1 = スポットライト |
color | float3 | RGB カラー(アルファ成分なし) |
intensity | float | ライト強度 |
direction | float3 | スポットライトの方向。ポイントライトでは無視 |
range | float | ライトの範囲 |
spotAngle | float | スポットライトのコーン角度(度)。ポイントライトでは無視 |
pad | float3 | アライメントパディング。代入不要 |