Lower provider-authored world key lights
This commit is contained in:
parent
42d9b4a948
commit
63a41712c5
5 changed files with 107 additions and 4 deletions
|
|
@ -29,6 +29,12 @@ own which semantic content belongs in a view, while EveUnity owns the native
|
|||
layer mapping and subtracts only those layers from the camera's configured
|
||||
culling mask.
|
||||
|
||||
World surfaces may also advertise a presentation-only directional key light
|
||||
through `keyLightDirection`, `keyLightColor`, and `keyLightIntensity`.
|
||||
EveUnity lowers those generic values into a transient Unity light and removes
|
||||
it when the world camera lease ends. The provider owns the lighting design;
|
||||
the light never becomes physics, visibility, or gameplay authority.
|
||||
|
||||
Retained provider feedback is lowered without becoming Unity authority.
|
||||
`EveUnityFeedbackPresenter` emits each new `feedback.event` identity once, and
|
||||
`EveUnityShotReceiptPresenter` does the same for `shot.receipt` trajectories.
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ namespace GameCult.Eve.UnityScene
|
|||
private float _previousReflectionIntensity;
|
||||
private Camera? _environmentCamera;
|
||||
private CameraClearFlags _previousCameraClearFlags;
|
||||
private GameObject? _keyLightObject;
|
||||
|
||||
public EveUnityPlayableWorldClientHost? Host
|
||||
{
|
||||
|
|
@ -124,6 +125,7 @@ namespace GameCult.Eve.UnityScene
|
|||
|
||||
var cameraComponent = camera.GetComponent<Camera>();
|
||||
ApplyAmbientEnvironment(activeWorld, cameraComponent, skybox, reflection);
|
||||
ApplyKeyLight(activeWorld);
|
||||
if (cameraComponent != null && _renderPolicySource != null)
|
||||
{
|
||||
var cullingMask = cameraComponent.cullingMask;
|
||||
|
|
@ -217,7 +219,14 @@ namespace GameCult.Eve.UnityScene
|
|||
!IsFinite(world.AmbientLightG) ||
|
||||
!IsFinite(world.AmbientLightB) ||
|
||||
!IsFinite(world.AmbientLightIntensity) ||
|
||||
!IsFinite(world.ReflectionIntensity))
|
||||
!IsFinite(world.ReflectionIntensity) ||
|
||||
!IsFinite(world.KeyLightDirectionX) ||
|
||||
!IsFinite(world.KeyLightDirectionY) ||
|
||||
!IsFinite(world.KeyLightDirectionZ) ||
|
||||
!IsFinite(world.KeyLightColorR) ||
|
||||
!IsFinite(world.KeyLightColorG) ||
|
||||
!IsFinite(world.KeyLightColorB) ||
|
||||
!IsFinite(world.KeyLightIntensity))
|
||||
return false;
|
||||
var assets = host.NativeAssetProvider;
|
||||
if (!string.IsNullOrWhiteSpace(world.SkyboxAssetRef))
|
||||
|
|
@ -245,6 +254,54 @@ namespace GameCult.Eve.UnityScene
|
|||
return true;
|
||||
}
|
||||
|
||||
private void ApplyKeyLight(EveUnityPlayableWorldProjection world)
|
||||
{
|
||||
var direction = new Vector3(
|
||||
world.KeyLightDirectionX,
|
||||
world.KeyLightDirectionY,
|
||||
world.KeyLightDirectionZ);
|
||||
if (world.KeyLightIntensity <= 0f || direction.sqrMagnitude <= 0.000001f)
|
||||
{
|
||||
ReleaseKeyLight();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_keyLightObject == null)
|
||||
{
|
||||
_keyLightObject = new GameObject("Eve World Key Light");
|
||||
_keyLightObject.transform.SetParent(transform, worldPositionStays: false);
|
||||
var created = _keyLightObject.AddComponent<Light>();
|
||||
created.type = LightType.Directional;
|
||||
created.shadows = LightShadows.None;
|
||||
}
|
||||
|
||||
var light = _keyLightObject.GetComponent<Light>();
|
||||
light.color = new Color(
|
||||
Mathf.Max(0f, world.KeyLightColorR),
|
||||
Mathf.Max(0f, world.KeyLightColorG),
|
||||
Mathf.Max(0f, world.KeyLightColorB),
|
||||
1f);
|
||||
light.intensity = Mathf.Max(0f, world.KeyLightIntensity);
|
||||
var normalized = direction.normalized;
|
||||
var up = Mathf.Abs(Vector3.Dot(normalized, Vector3.up)) > 0.999f
|
||||
? Vector3.forward
|
||||
: Vector3.up;
|
||||
_keyLightObject.transform.rotation = Quaternion.LookRotation(normalized, up);
|
||||
_keyLightObject.SetActive(true);
|
||||
}
|
||||
|
||||
private void ReleaseKeyLight()
|
||||
{
|
||||
if (_keyLightObject == null)
|
||||
return;
|
||||
_keyLightObject.SetActive(false);
|
||||
if (Application.isPlaying)
|
||||
Destroy(_keyLightObject);
|
||||
else
|
||||
DestroyImmediate(_keyLightObject);
|
||||
_keyLightObject = null;
|
||||
}
|
||||
|
||||
private static bool IsFinite(float value) => !float.IsNaN(value) && !float.IsInfinity(value);
|
||||
|
||||
private void ApplyAmbientEnvironment(
|
||||
|
|
@ -307,6 +364,7 @@ namespace GameCult.Eve.UnityScene
|
|||
|
||||
private void RestoreAmbientEnvironment()
|
||||
{
|
||||
ReleaseKeyLight();
|
||||
if (!_ownsAmbientEnvironment) return;
|
||||
var environmentChanged = !ReferenceEquals(RenderSettings.skybox, _previousSkybox);
|
||||
RenderSettings.ambientMode = _previousAmbientMode;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,10 @@ namespace GameCult.Eve.UnityScene
|
|||
worldRoot.GetProp("lookModel"),
|
||||
worldRoot.GetProp("skyboxAssetRef"),
|
||||
worldRoot.GetProp("reflectionAssetRef"),
|
||||
ParseFloat(worldRoot.GetProp("reflectionIntensity"), 1f));
|
||||
ParseFloat(worldRoot.GetProp("reflectionIntensity"), 1f),
|
||||
ParseVector3(worldRoot.GetProp("keyLightDirection")),
|
||||
ParseVector3(worldRoot.GetProp("keyLightColor")),
|
||||
ParseFloat(worldRoot.GetProp("keyLightIntensity"), 0f));
|
||||
}
|
||||
|
||||
private static EveUnityPlayableWorldEntity BuildPlayableEntity(EveSurfaceComponent component)
|
||||
|
|
@ -369,7 +372,10 @@ namespace GameCult.Eve.UnityScene
|
|||
string lookModel = "",
|
||||
string skyboxAssetRef = "",
|
||||
string reflectionAssetRef = "",
|
||||
float reflectionIntensity = 1f)
|
||||
float reflectionIntensity = 1f,
|
||||
(float x, float y, float z) keyLightDirection = default,
|
||||
(float r, float g, float b) keyLightColor = default,
|
||||
float keyLightIntensity = 0f)
|
||||
{
|
||||
WorldRootId = worldRootId ?? "";
|
||||
StatePointerId = statePointerId ?? "";
|
||||
|
|
@ -406,6 +412,13 @@ namespace GameCult.Eve.UnityScene
|
|||
SkyboxAssetRef = skyboxAssetRef ?? "";
|
||||
ReflectionAssetRef = reflectionAssetRef ?? "";
|
||||
ReflectionIntensity = reflectionIntensity;
|
||||
KeyLightDirectionX = keyLightDirection.x;
|
||||
KeyLightDirectionY = keyLightDirection.y;
|
||||
KeyLightDirectionZ = keyLightDirection.z;
|
||||
KeyLightColorR = keyLightColor.r;
|
||||
KeyLightColorG = keyLightColor.g;
|
||||
KeyLightColorB = keyLightColor.b;
|
||||
KeyLightIntensity = keyLightIntensity;
|
||||
}
|
||||
|
||||
public string WorldRootId { get; }
|
||||
|
|
@ -468,6 +481,20 @@ namespace GameCult.Eve.UnityScene
|
|||
|
||||
public float ReflectionIntensity { get; }
|
||||
|
||||
public float KeyLightDirectionX { get; }
|
||||
|
||||
public float KeyLightDirectionY { get; }
|
||||
|
||||
public float KeyLightDirectionZ { get; }
|
||||
|
||||
public float KeyLightColorR { get; }
|
||||
|
||||
public float KeyLightColorG { get; }
|
||||
|
||||
public float KeyLightColorB { get; }
|
||||
|
||||
public float KeyLightIntensity { get; }
|
||||
|
||||
public string FocusCommand { get; }
|
||||
|
||||
public string TargetCommand { get; }
|
||||
|
|
|
|||
|
|
@ -1159,6 +1159,14 @@ namespace GameCult.Eve.UnityScene.Tests
|
|||
Assert.That(RenderSettings.customReflectionTexture, Is.SameAs(reflectionCubemap));
|
||||
Assert.That(RenderSettings.reflectionIntensity, Is.EqualTo(1f).Within(0.001f));
|
||||
Assert.That(camera.clearFlags, Is.EqualTo(CameraClearFlags.Skybox));
|
||||
var keyLightTransform = hostObject.transform.Find("Eve World Key Light");
|
||||
Assert.That(keyLightTransform, Is.Not.Null);
|
||||
var keyLight = keyLightTransform.GetComponent<Light>();
|
||||
Assert.That(keyLight.type, Is.EqualTo(LightType.Directional));
|
||||
Assert.That(keyLight.intensity, Is.EqualTo(0.75f).Within(0.001f));
|
||||
Assert.That(keyLight.color, Is.EqualTo(new Color(1f, 0.95f, 0.9f, 1f)));
|
||||
Assert.That(Vector3.Dot(keyLightTransform.forward, new Vector3(0.4f, -1f, 0.25f).normalized),
|
||||
Is.GreaterThan(0.999f));
|
||||
Assert.That(nativeAssets.LastBinding?.AssetRef, Is.EqualTo("texture.environment.reflection"));
|
||||
Assert.That(nativeAssets.LastBinding?.EntityKind, Is.Empty);
|
||||
|
||||
|
|
@ -1210,6 +1218,7 @@ namespace GameCult.Eve.UnityScene.Tests
|
|||
Is.EqualTo(10f * (1f - Mathf.Exp(-0.5f))).Within(0.001f));
|
||||
rig.CameraTransform = null;
|
||||
Assert.That(host.ActiveCameraTransform, Is.Null);
|
||||
Assert.That(hostObject.transform.Find("Eve World Key Light"), Is.Null);
|
||||
aim.RefreshNow();
|
||||
Assert.That(aim.ViewDotVisible, Is.False);
|
||||
Assert.That(RenderSettings.ambientMode, Is.EqualTo(ambientMode));
|
||||
|
|
@ -1895,6 +1904,9 @@ namespace GameCult.Eve.UnityScene.Tests
|
|||
["skyboxAssetRef"] = skyboxAssetRef,
|
||||
["reflectionAssetRef"] = reflectionAssetRef,
|
||||
["reflectionIntensity"] = "1",
|
||||
["keyLightDirection"] = "0.4,-1,0.25",
|
||||
["keyLightColor"] = "1,0.95,0.9",
|
||||
["keyLightIntensity"] = "0.75",
|
||||
["excludedRenderChannels"] = "map",
|
||||
["playerEntityId"] = "player-vanguard",
|
||||
["movementCommand"] = "aetheria.daemon.move_intent",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "org.gamecult.eve.unity-scene",
|
||||
"displayName": "Eve Unity Scene Lowering",
|
||||
"version": "0.3.26",
|
||||
"version": "0.3.27",
|
||||
"unity": "2021.3",
|
||||
"description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.",
|
||||
"dependencies": {
|
||||
|
|
|
|||
Reference in a new issue