Camo: generalize brightness + add persistent saturation

Move brightness out of the half-lambert diffuse term to a final exposure
multiply on the whole shaded body color (diffuse + GI + specular), and add
a saturation grade (0 = neutral, -1 = grayscale, >0 = boosted) on the same
final stage. Saturation rides as a 4th component on CamoKnobs (Vector3 ->
Vector4) so it inherits all three persistence paths: HUD JSON, network
replication (_camo NetworkVariable), and painting-slot metadata. Wires the
renamed Slider_Brightness and new Slider_Saturation. Bumps HudFileVersion
and PaintMetaVersion with load-time remaps so existing paintings keep their
look (old 1=neutral saturation remaps to 0=neutral).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 4.8 committed 2026-07-08 07:23:40 +02:00
1 parent 45b7de05e4
commit 50781e32d2
7 files changed
+87 -36

No files matched your search

+8 -8
View File
@@ -69,12 +69,12 @@ public class PlayerPaintSync : NetworkBehaviour
private readonly NetworkVariable<float> _emissionIntensity =
new(1f, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
// Per-player camo knobs on the PlayerCamoLit material (x = HalfLambert, y = its brightness,
// z = specular dampen) - material values like emission intensity, applied once the remote painter
// is ready and on every change. The default mirrors Player.mat's authored camo so the brief
// pre-publish spawn frame shows no flash.
private readonly NetworkVariable<Vector3> _camo =
new(new Vector3(0.5f, 0f, 0.1f), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
// Per-player camo knobs on the PlayerCamoLit material (x = HalfLambert, y = brightness,
// z = specular dampen, w = saturation) - material values like emission intensity, applied once the
// remote painter is ready and on every change. The default mirrors Player.mat's authored camo (with
// neutral saturation 0) so the brief pre-publish spawn frame shows no flash.
private readonly NetworkVariable<Vector4> _camo =
new(new Vector4(0.5f, 0f, 0.1f, 0f), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
private bool _camoApplyPending; // remote: apply _camo.Value to the material once IsReady / on change
// Painted-height knobs (x = occlusion AO threshold, y = relief normal intensity, z = parallax
@@ -246,7 +246,7 @@ public class PlayerPaintSync : NetworkBehaviour
// Apply on the next LateUpdate once the material is ready (the camo setters are a no-op before that,
// and on a fresh spawn the OnValueChanged may arrive before the painter's Start has built the instance).
private void OnCamoChanged(Vector3 previous, Vector3 current) => _camoApplyPending = true;
private void OnCamoChanged(Vector4 previous, Vector4 current) => _camoApplyPending = true;
private void OnHeightChanged(Vector3 previous, Vector3 current) => _heightApplyPending = true;
// ---- Live stamp stream (owner -> server -> remotes) ----
@@ -315,7 +315,7 @@ public class PlayerPaintSync : NetworkBehaviour
// published (it would briefly flatten remotes' lighting until the real value lands).
if (_painter && _painter.IsReady)
{
Vector3 camo = _painter.CamoKnobs;
Vector4 camo = _painter.CamoKnobs;
if (_camo.Value != camo)
_camo.Value = camo;