From 2fa4524a7ff58105c34327e70cd64eb8df2eaec7 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 16 Jul 2026 00:16:52 +0100 Subject: [PATCH] Lower provider post-process profiles --- TestProject/Packages/packages-lock.json | 102 ++++++++++++++++++ .../Runtime/EveUnityPlayableWorldCameraRig.cs | 97 ++++++++++++++++- .../Runtime/EveUnitySceneSurfaceLowerer.cs | 5 + .../Runtime/GameCult.Eve.UnityScene.asmdef | 4 +- .../EveUnitySceneSurfaceLowererTests.cs | 21 +++- .../GameCult.Eve.UnityScene.Tests.asmdef | 4 +- .../org.gamecult.eve.unity-scene/package.json | 5 +- 7 files changed, 228 insertions(+), 10 deletions(-) diff --git a/TestProject/Packages/packages-lock.json b/TestProject/Packages/packages-lock.json index ea3990d..f6390b8 100644 --- a/TestProject/Packages/packages-lock.json +++ b/TestProject/Packages/packages-lock.json @@ -1,5 +1,27 @@ { "dependencies": { + "com.unity.burst": { + "version": "1.8.29", + "depth": 3, + "source": "registry", + "dependencies": { + "com.unity.mathematics": "1.2.1", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.collections": { + "version": "6.4.0", + "depth": 3, + "source": "builtin", + "dependencies": { + "com.unity.burst": "1.8.23", + "com.unity.mathematics": "1.3.2", + "com.unity.nuget.mono-cecil": "1.11.5", + "com.unity.test-framework": "1.4.6", + "com.unity.test-framework.performance": "3.0.3" + } + }, "com.unity.ext.nunit": { "version": "2.0.5", "depth": 1, @@ -13,6 +35,60 @@ "dependencies": {}, "url": "https://packages.unity.com" }, + "com.unity.nuget.mono-cecil": { + "version": "1.11.6", + "depth": 4, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.render-pipelines.core": { + "version": "17.4.0", + "depth": 2, + "source": "builtin", + "dependencies": { + "com.unity.burst": "1.8.14", + "com.unity.mathematics": "1.3.2", + "com.unity.ugui": "2.0.0", + "com.unity.collections": "2.4.3", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.render-pipelines.universal": { + "version": "17.4.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.render-pipelines.core": "17.4.0", + "com.unity.shadergraph": "17.4.0", + "com.unity.render-pipelines.universal-config": "17.4.0" + } + }, + "com.unity.render-pipelines.universal-config": { + "version": "17.4.0", + "depth": 2, + "source": "builtin", + "dependencies": { + "com.unity.render-pipelines.core": "17.4.0" + } + }, + "com.unity.searcher": { + "version": "4.9.4", + "depth": 3, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.shadergraph": { + "version": "17.4.0", + "depth": 2, + "source": "builtin", + "dependencies": { + "com.unity.render-pipelines.core": "17.4.0", + "com.unity.searcher": "4.9.3" + } + }, "com.unity.test-framework": { "version": "1.6.0", "depth": 0, @@ -23,6 +99,25 @@ "com.unity.modules.jsonserialize": "1.0.0" } }, + "com.unity.test-framework.performance": { + "version": "3.4.0", + "depth": 4, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.33", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ugui": { + "version": "2.0.0", + "depth": 3, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0" + } + }, "org.gamecult.cultlib": { "version": "file:../../artifacts/test-dependencies/org.gamecult.cultlib", "depth": 0, @@ -54,6 +149,7 @@ "org.gamecult.eve.plugin-fields": "0.2.3", "org.gamecult.eve.surface": "0.2.2", "com.unity.mathematics": "1.3.2", + "com.unity.render-pipelines.universal": "17.4.0", "com.unity.modules.particlesystem": "1.0.0" } }, @@ -107,6 +203,12 @@ "source": "builtin", "dependencies": {} }, + "com.unity.modules.terrain": { + "version": "1.0.0", + "depth": 3, + "source": "builtin", + "dependencies": {} + }, "com.unity.modules.ui": { "version": "1.0.0", "depth": 1, diff --git a/packages/org.gamecult.eve.unity-scene/Runtime/EveUnityPlayableWorldCameraRig.cs b/packages/org.gamecult.eve.unity-scene/Runtime/EveUnityPlayableWorldCameraRig.cs index ded0d3a..b0944e1 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/EveUnityPlayableWorldCameraRig.cs +++ b/packages/org.gamecult.eve.unity-scene/Runtime/EveUnityPlayableWorldCameraRig.cs @@ -1,5 +1,6 @@ using UnityEngine; using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; #nullable enable @@ -34,6 +35,11 @@ namespace GameCult.Eve.UnityScene private Camera? _environmentCamera; private CameraClearFlags _previousCameraClearFlags; private GameObject? _keyLightObject; + private GameObject? _postProcessVolumeObject; + private Volume? _postProcessVolume; + private UniversalAdditionalCameraData? _postProcessCameraData; + private bool _createdPostProcessCameraData; + private bool _previousRenderPostProcessing; public EveUnityPlayableWorldClientHost? Host { @@ -108,7 +114,7 @@ namespace GameCult.Eve.UnityScene ReleaseCamera(); return false; } - if (!TryResolveEnvironment(resolvedHost, activeWorld, out var skybox, out var reflection)) + if (!TryResolveEnvironment(resolvedHost, activeWorld, out var skybox, out var reflection, out var postProcessProfile)) { ReleaseRig(); return false; @@ -127,7 +133,12 @@ namespace GameCult.Eve.UnityScene _environmentOwner = this; var cameraComponent = camera.GetComponent(); - ApplyAmbientEnvironment(activeWorld, cameraComponent, skybox, reflection); + if (postProcessProfile != null && cameraComponent == null) + { + ReleaseRig(); + return false; + } + ApplyAmbientEnvironment(activeWorld, cameraComponent, skybox, reflection, postProcessProfile); ApplyKeyLight(activeWorld); if (cameraComponent != null && _renderPolicySource != null) { @@ -279,10 +290,12 @@ namespace GameCult.Eve.UnityScene EveUnityPlayableWorldClientHost host, EveUnityPlayableWorldProjection world, out Material? skybox, - out Cubemap? reflection) + out Cubemap? reflection, + out VolumeProfile? postProcessProfile) { skybox = null; reflection = null; + postProcessProfile = null; if (!IsFinite(world.AmbientLightR) || !IsFinite(world.AmbientLightG) || !IsFinite(world.AmbientLightB) || @@ -319,6 +332,17 @@ namespace GameCult.Eve.UnityScene if (reflection == null) return false; } + if (!string.IsNullOrWhiteSpace(world.PostProcessProfileAssetRef)) + { + postProcessProfile = assets?.ResolveAsset( + new EveUnityPlayableWorldAssetBinding( + world.PostProcessProfileAssetRef, + "", + "provider-asset-ref"), + typeof(VolumeProfile)) as VolumeProfile; + if (postProcessProfile == null) + return false; + } return true; } @@ -376,7 +400,8 @@ namespace GameCult.Eve.UnityScene EveUnityPlayableWorldProjection world, Camera? camera, Material? skybox, - Cubemap? reflection) + Cubemap? reflection, + VolumeProfile? postProcessProfile) { var environmentChanged = !ReferenceEquals(RenderSettings.skybox, skybox); if (!_ownsAmbientEnvironment) @@ -428,11 +453,75 @@ namespace GameCult.Eve.UnityScene } if (environmentChanged) DynamicGI.UpdateEnvironment(); + ApplyPostProcess(camera, postProcessProfile); + } + + private void ApplyPostProcess(Camera? camera, VolumeProfile? profile) + { + if (profile == null) + { + RestorePostProcess(); + return; + } + if (camera == null) + return; + if (_postProcessCameraData != null && !ReferenceEquals(_postProcessCameraData.gameObject, camera.gameObject)) + RestorePostProcess(); + if (_postProcessCameraData == null) + { + _postProcessCameraData = camera.GetComponent(); + _createdPostProcessCameraData = _postProcessCameraData == null; + if (_postProcessCameraData == null) + _postProcessCameraData = camera.gameObject.AddComponent(); + _previousRenderPostProcessing = _postProcessCameraData.renderPostProcessing; + } + _postProcessCameraData.renderPostProcessing = true; + if (_postProcessVolumeObject == null) + { + _postProcessVolumeObject = new GameObject("Eve World Post Process"); + _postProcessVolumeObject.transform.SetParent(transform, worldPositionStays: false); + _postProcessVolume = _postProcessVolumeObject.AddComponent(); + _postProcessVolume.isGlobal = true; + _postProcessVolume.priority = 1000f; + _postProcessVolume.weight = 1f; + } + _postProcessVolume!.sharedProfile = profile; + _postProcessVolumeObject.SetActive(true); + } + + private void RestorePostProcess() + { + if (_postProcessCameraData != null) + { + if (_createdPostProcessCameraData) + { + if (Application.isPlaying) + Destroy(_postProcessCameraData); + else + DestroyImmediate(_postProcessCameraData); + } + else + { + _postProcessCameraData.renderPostProcessing = _previousRenderPostProcessing; + } + } + _postProcessCameraData = null; + _createdPostProcessCameraData = false; + if (_postProcessVolumeObject != null) + { + if (Application.isPlaying) + Destroy(_postProcessVolumeObject); + else + DestroyImmediate(_postProcessVolumeObject); + } + _postProcessVolumeObject = null; + _postProcessVolume = null; } private void RestoreAmbientEnvironment() { ReleaseKeyLight(); + RestorePostProcess(); if (!_ownsAmbientEnvironment) return; var environmentChanged = !ReferenceEquals(RenderSettings.skybox, _previousSkybox); RenderSettings.ambientMode = _previousAmbientMode; diff --git a/packages/org.gamecult.eve.unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs b/packages/org.gamecult.eve.unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs index bb2536d..462336f 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs +++ b/packages/org.gamecult.eve.unity-scene/Runtime/EveUnitySceneSurfaceLowerer.cs @@ -147,6 +147,7 @@ namespace GameCult.Eve.UnityScene worldRoot.GetProp("skyboxAssetRef"), worldRoot.GetProp("reflectionAssetRef"), ParseFloat(worldRoot.GetProp("reflectionIntensity"), 1f), + worldRoot.GetProp("postProcessProfileAssetRef"), ParseVector3(worldRoot.GetProp("keyLightDirection")), ParseVector3(worldRoot.GetProp("keyLightColor")), ParseFloat(worldRoot.GetProp("keyLightIntensity"), 0f), @@ -390,6 +391,7 @@ namespace GameCult.Eve.UnityScene string skyboxAssetRef = "", string reflectionAssetRef = "", float reflectionIntensity = 1f, + string postProcessProfileAssetRef = "", (float x, float y, float z) keyLightDirection = default, (float r, float g, float b) keyLightColor = default, float keyLightIntensity = 0f, @@ -431,6 +433,7 @@ namespace GameCult.Eve.UnityScene SkyboxAssetRef = skyboxAssetRef ?? ""; ReflectionAssetRef = reflectionAssetRef ?? ""; ReflectionIntensity = reflectionIntensity; + PostProcessProfileAssetRef = postProcessProfileAssetRef ?? ""; KeyLightDirectionX = keyLightDirection.x; KeyLightDirectionY = keyLightDirection.y; KeyLightDirectionZ = keyLightDirection.z; @@ -504,6 +507,8 @@ namespace GameCult.Eve.UnityScene public float ReflectionIntensity { get; } + public string PostProcessProfileAssetRef { get; } + public float KeyLightDirectionX { get; } public float KeyLightDirectionY { get; } diff --git a/packages/org.gamecult.eve.unity-scene/Runtime/GameCult.Eve.UnityScene.asmdef b/packages/org.gamecult.eve.unity-scene/Runtime/GameCult.Eve.UnityScene.asmdef index 784339a..334de2e 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/GameCult.Eve.UnityScene.asmdef +++ b/packages/org.gamecult.eve.unity-scene/Runtime/GameCult.Eve.UnityScene.asmdef @@ -4,7 +4,9 @@ "references": [ "GameCult.Eve.Surface", "GameCult.Eve.PluginFields", - "Unity.Mathematics" + "Unity.Mathematics", + "Unity.RenderPipelines.Core.Runtime", + "Unity.RenderPipelines.Universal.Runtime" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs b/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs index 881c883..0f10bce 100644 --- a/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs +++ b/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs @@ -9,6 +9,7 @@ using GameCult.Mesh; using NUnit.Framework; using UnityEngine; using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; #nullable enable @@ -416,6 +417,7 @@ namespace GameCult.Eve.UnityScene.Tests Assert.That(projection.PlayableWorld.AmbientLightIntensity, Is.EqualTo(1.46f)); Assert.That(projection.PlayableWorld.SkyboxAssetRef, Is.Empty); Assert.That(projection.PlayableWorld.ReflectionAssetRef, Is.Empty); + Assert.That(projection.PlayableWorld.PostProcessProfileAssetRef, Is.Empty); Assert.That(projection.PlayableWorld.ReflectionIntensity, Is.EqualTo(1f)); Assert.That(projection.PlayableWorld.ExcludedRenderChannels, Is.EqualTo(new[] { "map" })); Assert.That(projection.PlayableWorld.PlayerEntityId, Is.EqualTo("player-vanguard")); @@ -1100,6 +1102,7 @@ namespace GameCult.Eve.UnityScene.Tests var previousReflectionIntensity = RenderSettings.reflectionIntensity; Material? skyboxMaterial = null; Cubemap? reflectionCubemap = null; + VolumeProfile? postProcessProfile = null; try { @@ -1109,13 +1112,16 @@ namespace GameCult.Eve.UnityScene.Tests Assert.That(skyboxShader, Is.Not.Null); skyboxMaterial = new Material(skyboxShader!); reflectionCubemap = new Cubemap(4, TextureFormat.RGBA32, false); + postProcessProfile = ScriptableObject.CreateInstance(); nativeAssets.Set("material.environment.skybox", skyboxMaterial); nativeAssets.Set("texture.environment.reflection", reflectionCubemap); + nativeAssets.Set("profile.environment.flight", postProcessProfile); provider.Set( new EveUnitySceneProviderSurfaceDocument( PlayableArpgDocument( skyboxAssetRef: "material.environment.skybox", - reflectionAssetRef: "texture.environment.reflection"), + reflectionAssetRef: "texture.environment.reflection", + postProcessProfileAssetRef: "profile.environment.flight"), Advertisement("aetheria.daemon.game"), "cultmesh://aetheria/eve/surfaces/aetheria.daemon.game", 1), @@ -1165,6 +1171,11 @@ 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)); + Assert.That(camera.GetComponent(), Is.Not.Null); + Assert.That(camera.GetComponent().renderPostProcessing, Is.True); + var postProcessTransform = hostObject.transform.Find("Eve World Post Process"); + Assert.That(postProcessTransform, Is.Not.Null); + Assert.That(postProcessTransform.GetComponent().sharedProfile, Is.SameAs(postProcessProfile)); var keyLightTransform = hostObject.transform.Find("Eve World Key Light"); Assert.That(keyLightTransform, Is.Not.Null); var keyLight = keyLightTransform.GetComponent(); @@ -1173,7 +1184,7 @@ namespace GameCult.Eve.UnityScene.Tests 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?.AssetRef, Is.EqualTo("profile.environment.flight")); Assert.That(nativeAssets.LastBinding?.EntityKind, Is.Empty); var secondaryHost = secondaryHostObject.AddComponent(); @@ -1225,6 +1236,8 @@ namespace GameCult.Eve.UnityScene.Tests rig.CameraTransform = null; Assert.That(host.ActiveCameraTransform, Is.Null); Assert.That(hostObject.transform.Find("Eve World Key Light"), Is.Null); + Assert.That(hostObject.transform.Find("Eve World Post Process"), Is.Null); + Assert.That(camera.GetComponent(), Is.Null); aim.RefreshNow(); Assert.That(aim.ViewDotVisible, Is.False); Assert.That(RenderSettings.ambientMode, Is.EqualTo(ambientMode)); @@ -1242,6 +1255,7 @@ namespace GameCult.Eve.UnityScene.Tests Assert.That(host.ActiveCameraTransform, Is.Null); nativeAssets.Set("material.environment.skybox", reflectionCubemap); nativeAssets.Set("texture.environment.reflection", skyboxMaterial); + nativeAssets.Set("profile.environment.flight", skyboxMaterial); Assert.That(rig.ApplyRig(0f), Is.False); Assert.That(host.ActiveCameraTransform, Is.Null); } @@ -1256,6 +1270,7 @@ namespace GameCult.Eve.UnityScene.Tests RenderSettings.reflectionIntensity = previousReflectionIntensity; if (skyboxMaterial != null) UnityEngine.Object.DestroyImmediate(skyboxMaterial); if (reflectionCubemap != null) UnityEngine.Object.DestroyImmediate(reflectionCubemap); + if (postProcessProfile != null) UnityEngine.Object.DestroyImmediate(postProcessProfile); UnityEngine.Object.DestroyImmediate(secondaryCameraObject); UnityEngine.Object.DestroyImmediate(secondaryHostObject); UnityEngine.Object.DestroyImmediate(secondaryRootObject); @@ -1838,6 +1853,7 @@ namespace GameCult.Eve.UnityScene.Tests string playerPosition = "0,0,0", string skyboxAssetRef = "", string reflectionAssetRef = "", + string postProcessProfileAssetRef = "", string cameraRig = "planar.top-down-follow.v1", string cameraDistance = "150", string cameraTargetScreenX = "0.9", @@ -1997,6 +2013,7 @@ namespace GameCult.Eve.UnityScene.Tests ["skyboxAssetRef"] = skyboxAssetRef, ["reflectionAssetRef"] = reflectionAssetRef, ["reflectionIntensity"] = "1", + ["postProcessProfileAssetRef"] = postProcessProfileAssetRef, ["keyLightDirection"] = "0.4,-1,0.25", ["keyLightColor"] = "1,0.95,0.9", ["keyLightIntensity"] = "0.75", diff --git a/packages/org.gamecult.eve.unity-scene/Tests/Editor/GameCult.Eve.UnityScene.Tests.asmdef b/packages/org.gamecult.eve.unity-scene/Tests/Editor/GameCult.Eve.UnityScene.Tests.asmdef index 4428a96..75ef6c3 100644 --- a/packages/org.gamecult.eve.unity-scene/Tests/Editor/GameCult.Eve.UnityScene.Tests.asmdef +++ b/packages/org.gamecult.eve.unity-scene/Tests/Editor/GameCult.Eve.UnityScene.Tests.asmdef @@ -5,7 +5,9 @@ "GameCult.Eve.Surface", "GameCult.Eve.UnityScene", "GameCult.Eve.UnityScene.CultMesh", - "GameCult.Eve.PluginFields" + "GameCult.Eve.PluginFields", + "Unity.RenderPipelines.Core.Runtime", + "Unity.RenderPipelines.Universal.Runtime" ], "includePlatforms": [ "Editor" diff --git a/packages/org.gamecult.eve.unity-scene/package.json b/packages/org.gamecult.eve.unity-scene/package.json index 4b65aa3..5822ed0 100644 --- a/packages/org.gamecult.eve.unity-scene/package.json +++ b/packages/org.gamecult.eve.unity-scene/package.json @@ -1,14 +1,15 @@ { "name": "org.gamecult.eve.unity-scene", "displayName": "Eve Unity Scene Lowering", - "version": "0.3.44", - "unity": "2021.3", + "version": "0.3.45", + "unity": "6000.0", "description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.", "dependencies": { "org.gamecult.cultlib": "1.0.13", "org.gamecult.eve.plugin-fields": "0.2.3", "org.gamecult.eve.surface": "0.2.2", "com.unity.mathematics": "1.3.2", + "com.unity.render-pipelines.universal": "17.4.0", "com.unity.modules.particlesystem": "1.0.0" }, "keywords": [