diff --git a/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveFieldsSplatBuffer.cs b/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveFieldsSplatBuffer.cs index ddd6abb..ecbb2a4 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveFieldsSplatBuffer.cs +++ b/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveFieldsSplatBuffer.cs @@ -12,7 +12,7 @@ namespace GameCult.Eve.UnityScene.Fields public const string ViewportToClipPropertyName = "_EveFieldsViewportToClip"; public const string ChannelFilterPropertyName = "_EveFieldsChannelFilter"; - private const int SplatStrideBytes = 80; + private const int SplatStrideBytes = 96; private EveFieldsGpuSplat[] splats = Array.Empty(); private GraphicsBuffer buffer; private int capacity; @@ -54,6 +54,7 @@ namespace GameCult.Eve.UnityScene.Fields RotationChannelFalloff = new Vector4((float)Read(source.RotationCos, index, 1), (float)Read(source.RotationSin, index, 0), channel, Read(source.Falloff, index, EveFieldsSplatFalloffs.Smooth)), LayerSource = new Vector4(layer, Read(source.SourceKind, index, EveFieldsSplatSourceKinds.Constant), (float)Read(source.AnimationSpeed, index, 0), (float)Read(source.SourceFlags, index, 0)), SourceFrequencyPhase = new Vector4((float)Read(source.FrequencyX, index, 1), (float)Read(source.FrequencyY, index, 1), (float)Read(source.PhaseX, index, 0), (float)Read(source.PhaseY, index, 0)), + FalloffParameters = new Vector4((float)Read(source.FalloffScale, index, 1), (float)Read(source.FalloffExponent, index, 1), 0, 0), Value = new Vector4((float)Read(source.ValueR, index, 0), (float)Read(source.ValueG, index, 0), (float)Read(source.ValueB, index, 0), (float)Read(source.ValueA, index, 1)) }; } @@ -99,6 +100,7 @@ namespace GameCult.Eve.UnityScene.Fields public Vector4 RotationChannelFalloff; public Vector4 LayerSource; public Vector4 SourceFrequencyPhase; + public Vector4 FalloffParameters; public Vector4 Value; } } diff --git a/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveFieldsSplatsCore.hlsl b/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveFieldsSplatsCore.hlsl index a7ec7a9..a37a411 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveFieldsSplatsCore.hlsl +++ b/packages/org.gamecult.eve.unity-scene/Runtime/Fields/EveFieldsSplatsCore.hlsl @@ -7,6 +7,7 @@ struct EveFieldsSplat float4 rotationChannelFalloff; float4 layerSource; float4 sourceFrequencyPhase; + float4 falloffParameters; float4 value; }; @@ -58,12 +59,17 @@ Varyings Vert(uint vertexId : SV_VertexID, uint instanceId : SV_InstanceID) return output; } -float ResolveFalloff(float2 localUv, int falloff) +float ResolveFalloff(float2 localUv, int falloff, float scale, float exponent) { float distance01 = saturate(length(localUv)); if (falloff == 0) return 1; if (falloff == 1) return saturate(1 - distance01); if (falloff == 3) return smoothstep(0, 1, distance01); + if (falloff == 4) + { + float pulseDistance = distance01 * max(0, scale); + return pow(saturate(1 - pulseDistance * pulseDistance), max(0.0001, exponent)); + } return 1 - smoothstep(0, 1, distance01); } @@ -72,7 +78,11 @@ float4 Frag(Varyings input) : SV_Target EveFieldsSplat splat = _EveFieldsSplats[input.instanceId]; int channel = (int)round(splat.rotationChannelFalloff.z); if (_EveFieldsChannelFilter >= 0 && channel != _EveFieldsChannelFilter) discard; - float alpha = ResolveFalloff(input.localUv, (int)round(splat.rotationChannelFalloff.w)); + float alpha = ResolveFalloff( + input.localUv, + (int)round(splat.rotationChannelFalloff.w), + splat.falloffParameters.x, + splat.falloffParameters.y); clip(alpha - 0.0001); int sourceKind = (int)round(splat.layerSource.y); float source = 1; 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 cf10e64..365d2e4 100644 --- a/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveFieldsUnitySceneProjectionTests.cs +++ b/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveFieldsUnitySceneProjectionTests.cs @@ -131,6 +131,49 @@ namespace GameCult.Eve.UnityScene.Tests UnityEngine.Object.DestroyImmediate(host); } + [Test] + public void RasterizerLowersPortablePowerPulseParameters() + { + var document = new EveFieldsSplatsDocument + { + Viewport = new EveFieldsViewport { MinX = -1, MinY = -1, MaxX = 1, MaxY = 1 }, + Splats = new EveFieldsSplatSoa + { + Count = 1, + CenterX = new[] { 0d }, + CenterY = new[] { 0d }, + HalfExtentX = new[] { 1d }, + HalfExtentY = new[] { 1d }, + RotationCos = new[] { 1d }, + RotationSin = new[] { 0d }, + Channel = new[] { 0 }, + Falloff = new[] { EveFieldsSplatFalloffs.PowerPulse }, + FalloffScale = new[] { 2d }, + FalloffExponent = new[] { 1d }, + ValueR = new[] { 1d }, + ValueA = new[] { 1d }, + LayerIndex = new[] { 0 }, + SourceKind = new[] { EveFieldsSplatSourceKinds.Constant } + } + }; + var host = new GameObject("eve-fields-power-pulse"); + var rasterizer = host.AddComponent(); + var output = rasterizer.Render(document, 128, 128); + var previous = RenderTexture.active; + RenderTexture.active = output; + var readback = new Texture2D(128, 128, TextureFormat.RGBAFloat, false, true); + readback.ReadPixels(new Rect(0, 0, 128, 128), 0, 0); + readback.Apply(); + RenderTexture.active = previous; + + Assert.That(readback.GetPixel(64, 64).r, Is.GreaterThan(0.95f)); + Assert.That(readback.GetPixel(80, 64).r, Is.InRange(0.65f, 0.85f)); + Assert.That(readback.GetPixel(96, 64).r, Is.LessThan(0.02f)); + + UnityEngine.Object.DestroyImmediate(readback); + UnityEngine.Object.DestroyImmediate(host); + } + private sealed class CaptureDocument : IEveFieldsSplatsDocument { public string Schema => EveFieldsSchemas.Splats; @@ -188,6 +231,8 @@ namespace GameCult.Eve.UnityScene.Tests public IReadOnlyList PhaseY => Zero; public IReadOnlyList AnimationSpeed => Zero; public IReadOnlyList SourceFlags => Zero; + public IReadOnlyList FalloffScale => One; + public IReadOnlyList FalloffExponent => One; } } } diff --git a/packages/org.gamecult.eve.unity-scene/package.json b/packages/org.gamecult.eve.unity-scene/package.json index 1dc9489..87d9d36 100644 --- a/packages/org.gamecult.eve.unity-scene/package.json +++ b/packages/org.gamecult.eve.unity-scene/package.json @@ -1,12 +1,12 @@ { "name": "org.gamecult.eve.unity-scene", "displayName": "Eve Unity Scene Lowering", - "version": "0.3.41", + "version": "0.3.42", "unity": "2021.3", "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.0", + "org.gamecult.eve.plugin-fields": "0.2.1", "org.gamecult.eve.surface": "0.2.2", "com.unity.mathematics": "1.3.2", "com.unity.modules.particlesystem": "1.0.0"