Color Adjustment Development Guide
The LCC Unity SDK supports editing operations such as highlighting, clipping, and color adjustment on 3DGS scenes. This guide introduces color adjustment operations: selecting an area through 2D projected textures, 3D geometry, or a mix of both, and adjusting the brightness, saturation, and contrast of the selected area, supporting normal selection and invert selection.
Note:
The current color adjustment feature is only a runtime display effect; it does not modify the original data file in any way and does not support saving or exporting the edit result. If you need to color-adjust, clip, and save data, use the XGRIDS LCC Editor software tool.
If you do not want to modify the data, you can also record the operations and replay them (execute the settings) after the data finishes loading next time.
Prerequisites
Color-adjusting a scene through the SDK requires the following conditions:
- Enter the edit state before loading data. The SDK is in the browsing state (View) by default, which provides the best performance and is recommended for normal browsing. To perform editing operations such as color adjustment, switch to the edit state via
SetEditorMode(true)before callingLoad. This method only takes effect if called before loading all the data. - Perform the color adjustment operation after data finishes loading. The color adjustment interface needs to be called after the scene data has fully loaded.
Step 1: Set up the scene
Prepare the GameObjects needed for color adjustment in the scene:
- Main Camera: the scene camera; 2D color adjustment uses its view and projection matrices.
- LCCManager: an empty GameObject with a normalized Transform, with the
LCCManagerscript added. - LCCRenderer: an empty GameObject with Transform set to Rotation.x = -90, Scale.x = -1 (aligned with the LCC data coordinate system), used to attach the
Tonescript written later. - 3D selection geometry (optional): auxiliary objects for 3D color adjustment. The example prepares one Cube (
Box1); moving and scaling it controls the position and size of the 3D color adjustment selection.
Note:
For settings related to the rendering camera, LCCManager, and LCCRenderer GameObjects, refer to the relevant sections of PC Quick Start Guide and Project Settings Optimization Guide.
Step 2: Understand the data structure
Color adjustment uses the ToneMix data structure, which can describe both a 2D texture selection and a 3D geometry selection at the same time, and carries the color adjustment parameters. The enums and structs used are as follows.
public enum SelectMode { normal, invert, clip } // normal selection, invert, real-time clipping
public enum OperationMode { normal, erase } // normal selection, erase selection
public enum ShapeType { box, sphere } // 3D Box selection, 3D Sphere selection
public enum EditType { Edit2D, Edit3D } // 2D edit, 3D edit
// Color adjustment selection
public struct ToneMix
{
public EditType editType; // edit type (required; determines whether 2D or 3D fields are used)
public Texture2D texture; // 2D mask texture (used by Edit2D)
public Matrix4x4 mv; // camera view matrix (used by Edit2D)
public Matrix4x4 mvp; // camera view projection matrix (used by Edit2D)
public ShapeType type; // geometry type (used by Edit3D)
public Matrix4x4 invMat; // geometry inverse matrix (used by Edit3D)
public OperationMode operation; // operation type (used by Edit3D)
public SelectMode mode; // selection mode (required)
public float brightness; // brightness, range [0, 3], default 1.0
public float saturation; // saturation, range [0, 3], default 1.0
public float contrast; // contrast, range [0, 3], default 1.0
public int lutid; // LUT table index (reserved), 0 means not used
}
There are three points to note about the color adjustment list:
- The list is ordered. Whether 2D or 3D, entries in the list take effect in order; make sure the order of addition matches your expectation.
- Invert must carry color adjustment data. This is the most critical difference between color adjustment and highlight/clipping — the invert of highlight/clipping is a pure command and does not need to be associated with data; but the invert entry of color adjustment, besides
mode = SelectMode.invert, must also setbrightness,saturation, andcontrast, to specify the color adjustment effect for the area outside the selection. - The maximum number of entries in a single list is 255. Exceeding it returns an error code.
Step 3: Understand the color adjustment APIs
All color-adjustment-related interfaces are provided by LCCManager, including one SetTone method and one exit method.
SetTone
// Return value: int
// 0: success
// 1: list is null or has 0 elements
// 2: list elements exceed the maximum of 255
public int SetTone(List<ToneMix> _Mix)
Performs color adjustment on the selected area, supporting brightness, saturation, and contrast adjustments. 2D texture entries and 3D geometry entries can be mixed in the same list.
QuitToneMode
// Return value: void
public void QuitToneMode()
Exits color adjustment mode and restores the scene's original colors.
Tip:
When switching color adjustment parameters or clearing the current color adjustment, call
QuitToneMode()first and then set the new color adjustment.
Step 4: 2D mask texture specification
2D color adjustment describes the selection through a mask texture, supporting various selection methods such as quadrilaterals, triangles, brushes, and lassos — simply mark the corresponding pixels in the texture with the selected value. When using 2D operations, the camera should be locked and the texture marked from a fixed viewpoint. The texture and pixel values have the following conventions:
- The texture is fixed at 1024 × 1024,
R8single channel, no Mipmap, point filtering (FilterMode.Point), and clamped sampling (TextureWrapMode.Clamp). - Pixel value conventions:
| Pixel value | Meaning |
|---|---|
128 | Default (not selected) |
240 | Selected |
180 | Deselect (erase the already selected area) |
0 | Clipping |
In a color adjustment scenario, only the two values 128 (default) and 240 (selected) are usually used.
Step 5: Write the script
Create a new C# script named Tone.cs. First complete the basic skeleton: in Start, enter the edit state and load data; after loading completes, set the load flag for the subsequent color adjustment methods to check.
using LCCCore;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Tone : MonoBehaviour
{
public LCCManager m_manager;
public string m_FilePath;
public GameObject m_Box1;
public Slider m_brightness;
public Slider m_saturation;
public Slider m_contrast;
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);
// Enter edit mode; must be called before 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;
}
// Color adjustment methods below
}
Note:
SetEditorMode(true)must be called beforeLoadto take effect; andSetTonemust be called after data finishes loading (after theonLoadCallbackcallback fires). The three slidersm_brightness,m_saturation, andm_contrastare used to dynamically adjust the color adjustment parameters at runtime and can be used as needed.
Step 6: Attach the script and set properties
- Attach the
Tone.csscript to the LCCRenderer GameObject. - In the Inspector window, drag the LCCManager GameObject onto the script's Manager property.
- Fill in the LCC file path in the File Path property.
- Drag
Box1in the scene onto the script's Box1 property, and drag the three sliders onto the Brightness, Saturation, and Contrast properties respectively, for 3D color adjustment and runtime parameter adjustment.

Set the Tone script properties in the Inspector
Step 7: Color adjustment operation examples
Add the methods below to the Tone class, and call the corresponding method after running and after data finishes loading.
Normal color adjustment
Construct an R8 mask texture, mark the pixels to color-adjust as 240 and the rest as 128, then construct ToneMix with the camera matrices, set brightness, saturation, and contrast, and add it to the list.
public void onTone()
{
// Texture size is fixed at 1024*1024; keep other properties the same as the example
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 means default, 240 means selected, 0 means clipping
else
_values[i] = 240;
}
_texture.SetPixelData(_values, 0);
List<ToneMix> _tMixs = new List<ToneMix>();
ToneMix _tmix01 = new ToneMix();
_tmix01.editType = EditType.Edit2D;
_tmix01.mv = m_camera.worldToCameraMatrix * this.transform.localToWorldMatrix;
_tmix01.texture = _texture;
_tmix01.mode = SelectMode.normal;
_tmix01.mvp = GL.GetGPUProjectionMatrix(m_camera.projectionMatrix, true) * m_camera.worldToCameraMatrix * this.transform.localToWorldMatrix;
_tmix01.brightness = 2.0f;
_tmix01.saturation = 2.0f;
_tmix01.contrast = 0.4f;
_tMixs.Add(_tmix01);
m_manager.SetTone(_tMixs);
}
Code explanation: a mask texture is built that selects the upper half of the screen (the screen origin is the lower-left corner), and a color adjustment of brightness 2.0, saturation 2.0, and contrast 0.4 is applied to the selected area. The example effect is as follows.
In actual use, you can use various selection tools such as rectangles, triangles, brushes, and lassos to select the corresponding positions on the mask, and also dynamically pass the values of brightness, saturation, and contrast through sliders.

Normal color adjustment effect
Invert color adjustment
The invert of color adjustment differs from highlight and clipping: the invert entry, besides setting mode = SelectMode.invert, must carry color adjustment data (brightness, saturation, contrast) to specify the color adjustment effect for the area outside the selection. Based on the normal color adjustment above, simply append an invert entry.
public void onToneInvert()
{
// Texture size is fixed at 1024*1024; keep other properties the same as the example
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 means default, 240 means selected, 0 means clipping
else
_values[i] = 240;
}
_texture.SetPixelData(_values, 0);
List<ToneMix> _tMixs = new List<ToneMix>();
// Normal selection color adjustment
ToneMix _tmix01 = new ToneMix();
_tmix01.editType = EditType.Edit2D;
_tmix01.mv = m_camera.worldToCameraMatrix * this.transform.localToWorldMatrix;
_tmix01.texture = _texture;
_tmix01.mode = SelectMode.normal;
_tmix01.mvp = GL.GetGPUProjectionMatrix(m_camera.projectionMatrix, true) * m_camera.worldToCameraMatrix * this.transform.localToWorldMatrix;
_tmix01.brightness = 2.0f;
_tmix01.saturation = 2.0f;
_tmix01.contrast = 0.4f;
_tMixs.Add(_tmix01);
// Invert: must carry color adjustment data (brightness/saturation/contrast), not a pure command
ToneMix _tmix02 = new ToneMix();
_tmix02.editType = EditType.Edit2D;
_tmix02.mode = SelectMode.invert;
_tmix02.brightness = 0.5f;
_tmix02.saturation = 0.5f;
_tmix02.contrast = 2.0f;
_tMixs.Add(_tmix02);
m_manager.SetTone(_tMixs);
}
Code explanation: an invert entry is appended on top of the normal color adjustment, applying a color adjustment of brightness 0.5, saturation 0.5, and contrast 2.0 to the area outside the selection. This way, different color adjustment parameters can be applied inside and outside the selection. The example effect is as follows.

Invert color adjustment effect
Note:
The invert of highlight and clipping is a pure command: appending an entry with
mode = SelectMode.invertis enough, with no other data required. But the invert entry of color adjustment must also setbrightness,saturation, andcontrast; otherwise the inverted area uses the default values (1.0) and does not achieve the expected effect.
Step 8: Exit color adjustment
Call QuitToneMode() to clear the current color adjustment and restore the scene's original colors.
public void onToneClear()
{
m_manager.QuitToneMode();
}
Key Steps
The key steps for color-adjusting a 3DGS scene:
- Call
SetEditorMode(true)before loading data to enter the edit state. - Call
SetToneafter data finishes loading (after theonLoadCallbackcallback fires, or triggered through a button/event). - Control the color adjustment effect through
ToneMix'sbrightness,saturation, andcontrast(range[0, 3], default1.0), and make sure the color adjustment list's order of addition matches your expectation. - The 2D mask texture is fixed at 1024 × 1024,
R8single channel; fill pixel values per convention (128default,240selected). - The color adjustment invert (
SelectMode.invert) must carrybrightness,saturation, andcontrastdata — this is the key difference from highlight/clipping invert. - When clearing or switching color adjustment, call
QuitToneMode()first.