From 02203ff134570c301ce58969397c296ee14e69ee Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 16 Jul 2026 19:25:57 +0100 Subject: [PATCH] Preserve Unity shader camera transform semantics --- .../Fields/EveUnityFieldsVolumeRenderer.cs | 5 +++- .../EveFieldsUnitySceneProjectionTests.cs | 30 +++++++++++++++++++ .../org.gamecult.eve.unity-scene/package.json | 2 +- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveUnityFieldsVolumeRenderer.cs b/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveUnityFieldsVolumeRenderer.cs index f4e823a..061d55c 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveUnityFieldsVolumeRenderer.cs +++ b/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveUnityFieldsVolumeRenderer.cs @@ -140,7 +140,7 @@ namespace GameCult.Eve.UnityScene.Fields var gpuProjection = GL.GetGPUProjectionMatrix(camera.projectionMatrix, true); var viewProjection = gpuProjection * camera.worldToCameraMatrix; SetMatrixPort("cameraInverseViewProjection", viewProjection.inverse); - SetMatrixPort("cameraToWorld", camera.cameraToWorldMatrix); + SetMatrixPort("cameraToWorld", CameraTransformToWorld(camera)); SetVectorPort("cameraProjectionExtents", ProjectionExtents(camera)); SetFloatPort("raymarchOffset", Halton(Time.frameCount & 1023, 3)); @@ -594,6 +594,9 @@ namespace GameCult.Eve.UnityScene.Fields return new Vector4(y * camera.aspect, y, 0f, 0f); } + private static Matrix4x4 CameraTransformToWorld(Camera camera) => + camera.transform.localToWorldMatrix; + private static float Halton(int index, int radix) { var result = 0f; diff --git a/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveFieldsUnitySceneProjectionTests.cs b/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveFieldsUnitySceneProjectionTests.cs index a8349a4..3591dbd 100644 --- a/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveFieldsUnitySceneProjectionTests.cs +++ b/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveFieldsUnitySceneProjectionTests.cs @@ -2,6 +2,7 @@ using System; using System.IO; using System.Linq; using System.Collections.Generic; +using System.Reflection; using GameCult.Eve.PluginFields; using GameCult.Eve.UnityScene.Fields; using NUnit.Framework; @@ -12,6 +13,35 @@ namespace GameCult.Eve.UnityScene.Tests { public sealed class EveFieldsUnitySceneProjectionTests { + [Test] + public void VolumeCameraToWorldPreservesUnityShaderPositiveZForward() + { + var cameraObject = new GameObject("eve-volume-camera-matrix"); + try + { + var camera = cameraObject.AddComponent(); + camera.transform.SetPositionAndRotation( + new Vector3(12f, -3f, 8f), + Quaternion.Euler(17f, 43f, -9f)); + var method = typeof(EveUnityFieldsVolumeRenderer).GetMethod( + "CameraTransformToWorld", + BindingFlags.NonPublic | BindingFlags.Static); + + Assert.That(method, Is.Not.Null); + var matrix = (Matrix4x4)method!.Invoke(null, new object[] { camera }); + Assert.That(Vector3.Dot( + matrix.MultiplyVector(Vector3.forward).normalized, + camera.transform.forward), Is.EqualTo(1f).Within(0.00001f)); + Assert.That(Vector3.Distance( + matrix.MultiplyPoint3x4(Vector3.zero), + camera.transform.position), Is.LessThan(0.00001f)); + } + finally + { + UnityEngine.Object.DestroyImmediate(cameraObject); + } + } + [Test] public void RasterizerConsumesPluginOwnedDocumentContract() { diff --git a/packages/org.gamecult.eve.unity-scene/package.json b/packages/org.gamecult.eve.unity-scene/package.json index 64b70e2..d3c13c8 100644 --- a/packages/org.gamecult.eve.unity-scene/package.json +++ b/packages/org.gamecult.eve.unity-scene/package.json @@ -1,7 +1,7 @@ { "name": "org.gamecult.eve.unity-scene", "displayName": "Eve Unity Scene Lowering", - "version": "0.3.57", + "version": "0.3.58", "unity": "6000.0", "description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.", "dependencies": {