Honor provider temporal reprojection semantics
This commit is contained in:
parent
1d23be18b6
commit
7588763999
3 changed files with 79 additions and 2 deletions
|
|
@ -28,6 +28,7 @@ namespace GameCult.Eve.UnityScene.Fields
|
|||
private readonly RenderTexture?[] _historyTextures = new RenderTexture?[2];
|
||||
private int _historyTextureIndex = -1;
|
||||
private Matrix4x4 _previousViewProjection;
|
||||
private Matrix4x4 _previousView;
|
||||
private EveUnityFieldsVolumePass? _renderPass;
|
||||
private string _activeNodeId = "";
|
||||
private long _rasterizedFrameId = -1;
|
||||
|
|
@ -160,7 +161,15 @@ namespace GameCult.Eve.UnityScene.Fields
|
|||
finalCloudTexture = _historyTextures[historyWriteIndex]!;
|
||||
SetTexturePort("currentSample", _raymarchTexture);
|
||||
SetTexturePort("history", historyReadTexture!);
|
||||
SetMatrixPort("previousViewProjection", _historyTextureIndex < 0 ? viewProjection : _previousViewProjection);
|
||||
SetMatrixPort(
|
||||
"previousViewProjection",
|
||||
_historyTextureIndex < 0
|
||||
? viewProjection
|
||||
: ResolvePreviousViewProjection(
|
||||
_programMetadata,
|
||||
_previousViewProjection,
|
||||
gpuProjection,
|
||||
_previousView));
|
||||
SetFloatPort("resetHistory", _historyTextureIndex < 0 ? 1f : 0f);
|
||||
}
|
||||
SetTexturePort("cloud", finalCloudTexture);
|
||||
|
|
@ -186,6 +195,7 @@ namespace GameCult.Eve.UnityScene.Fields
|
|||
{
|
||||
_historyTextureIndex = historyWriteIndex;
|
||||
_previousViewProjection = viewProjection;
|
||||
_previousView = camera.worldToCameraMatrix;
|
||||
}
|
||||
CompositeCount++;
|
||||
}
|
||||
|
|
@ -454,6 +464,20 @@ namespace GameCult.Eve.UnityScene.Fields
|
|||
{
|
||||
_historyTextureIndex = -1;
|
||||
_previousViewProjection = Matrix4x4.identity;
|
||||
_previousView = Matrix4x4.identity;
|
||||
}
|
||||
|
||||
public static Matrix4x4 ResolvePreviousViewProjection(
|
||||
IReadOnlyDictionary<string, string>? metadata,
|
||||
Matrix4x4 previousViewProjection,
|
||||
Matrix4x4 currentGpuProjection,
|
||||
Matrix4x4 previousView)
|
||||
{
|
||||
return metadata != null &&
|
||||
metadata.TryGetValue("unity.volume.matrixSemantic.previousViewProjection", out var semantic) &&
|
||||
string.Equals(semantic, "current-projection.previous-view.v1", StringComparison.Ordinal)
|
||||
? currentGpuProjection * previousView
|
||||
: previousViewProjection;
|
||||
}
|
||||
|
||||
private bool HasTemporalProgram() => ProgramPass("temporal") >= 0;
|
||||
|
|
@ -532,6 +556,10 @@ namespace GameCult.Eve.UnityScene.Fields
|
|||
!ValidPort(metadata, "matrix", "previousViewProjection") ||
|
||||
!ValidPort(metadata, "float", "resetHistory"))
|
||||
return Fail("Native volume temporal pass is missing a required history port.", out error);
|
||||
if (metadata.TryGetValue("unity.volume.matrixSemantic.previousViewProjection", out var semantic) &&
|
||||
!string.Equals(semantic, "previous-view-projection.v1", StringComparison.Ordinal) &&
|
||||
!string.Equals(semantic, "current-projection.previous-view.v1", StringComparison.Ordinal))
|
||||
return Fail("Native volume temporal pass has an unsupported previous-view-projection semantic.", out error);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -327,6 +327,55 @@ namespace GameCult.Eve.UnityScene.Tests
|
|||
Assert.That(EveUnityFieldsVolumeRenderer.TryValidateProgramMetadata(metadata, out var error), Is.True, error);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VolumeRendererUsesCurrentProjectionWithPreviousViewWhenAdvertised()
|
||||
{
|
||||
var metadata = RequiredVolumeProgramMetadata();
|
||||
metadata["unity.volume.matrixSemantic.previousViewProjection"] =
|
||||
"current-projection.previous-view.v1";
|
||||
var previousViewProjection = Matrix4x4.Translate(new Vector3(1f, 2f, 3f));
|
||||
var currentProjection = Matrix4x4.Scale(new Vector3(2f, 3f, 4f));
|
||||
var previousView = Matrix4x4.Rotate(Quaternion.Euler(10f, 20f, 30f));
|
||||
|
||||
var resolved = EveUnityFieldsVolumeRenderer.ResolvePreviousViewProjection(
|
||||
metadata,
|
||||
previousViewProjection,
|
||||
currentProjection,
|
||||
previousView);
|
||||
|
||||
Assert.That(resolved, Is.EqualTo(currentProjection * previousView));
|
||||
Assert.That(resolved, Is.Not.EqualTo(previousViewProjection));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VolumeRendererDefaultsToTruePreviousViewProjection()
|
||||
{
|
||||
var previousViewProjection = Matrix4x4.Translate(new Vector3(1f, 2f, 3f));
|
||||
|
||||
var resolved = EveUnityFieldsVolumeRenderer.ResolvePreviousViewProjection(
|
||||
RequiredVolumeProgramMetadata(),
|
||||
previousViewProjection,
|
||||
Matrix4x4.Scale(Vector3.one * 2f),
|
||||
Matrix4x4.Rotate(Quaternion.Euler(10f, 20f, 30f)));
|
||||
|
||||
Assert.That(resolved, Is.EqualTo(previousViewProjection));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VolumeProgramRejectsUnknownPreviousViewProjectionSemantic()
|
||||
{
|
||||
var metadata = RequiredVolumeProgramMetadata();
|
||||
metadata["unity.volume.pass.temporal"] = "1";
|
||||
metadata["unity.volume.texturePort.currentSample"] = "_CurrentVolume";
|
||||
metadata["unity.volume.texturePort.history"] = "_HistoryVolume";
|
||||
metadata["unity.volume.matrixPort.previousViewProjection"] = "_PreviousViewProjection";
|
||||
metadata["unity.volume.floatPort.resetHistory"] = "_ResetHistory";
|
||||
metadata["unity.volume.matrixSemantic.previousViewProjection"] = "made-up";
|
||||
|
||||
Assert.That(EveUnityFieldsVolumeRenderer.TryValidateProgramMetadata(metadata, out var error), Is.False);
|
||||
Assert.That(error, Does.Contain("previous-view-projection semantic"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VolumeProgramRejectsPartialTemporalLifecycle()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "org.gamecult.eve.unity-scene",
|
||||
"displayName": "Eve Unity Scene Lowering",
|
||||
"version": "0.3.59",
|
||||
"version": "0.3.60",
|
||||
"unity": "6000.0",
|
||||
"description": "Provider-agnostic Unity scene shell for gamecult.eve.surface.v1 interactive world surfaces.",
|
||||
"dependencies": {
|
||||
|
|
|
|||
Reference in a new issue