feat(render): implement Campaign AR and terrain fidelity
This commit is contained in:
parent
99cf26e00c
commit
7a5f96ede5
368 changed files with 50611 additions and 950 deletions
|
|
@ -0,0 +1,137 @@
|
|||
using System.Numerics;
|
||||
using AcDream.App.Rendering;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering;
|
||||
|
||||
public sealed class DirectionalShadowReceiverTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("atmospheric-world-hdr", false, true, false)]
|
||||
[InlineData("atmospheric-world-hdr", true, false, false)]
|
||||
[InlineData("vk-world", true, true, false)]
|
||||
[InlineData("atmospheric-world-hdr", true, true, true)]
|
||||
internal void RetailPipelineRemainsExactUnlessPackAndCurrentBindingAreActive(
|
||||
string pass,
|
||||
bool source,
|
||||
bool binding,
|
||||
bool expected) =>
|
||||
Assert.Equal(
|
||||
expected,
|
||||
DirectionalShadowReceiverPolicy.ShouldSelectReceiverPipeline(
|
||||
pass,
|
||||
source,
|
||||
binding));
|
||||
|
||||
[Fact]
|
||||
public void CascadeTransition_IsContinuousAcrossTheSplitInWorldMetres()
|
||||
{
|
||||
Vector4 splits = new(10f, 30f, 60f, 100f);
|
||||
|
||||
DirectionalShadowCascadeBlend atSplit =
|
||||
DirectionalShadowReceiverPolicy.SelectCascade(10f, splits, 4, 2f);
|
||||
DirectionalShadowCascadeBlend afterSplit =
|
||||
DirectionalShadowReceiverPolicy.SelectCascade(10.0001f, splits, 4, 2f);
|
||||
|
||||
Assert.Equal(0, atSplit.PrimaryCascade);
|
||||
Assert.Equal(1, atSplit.SecondaryCascade);
|
||||
Assert.Equal(1f, atSplit.SecondaryWeight, 5);
|
||||
Assert.Equal(1, afterSplit.PrimaryCascade);
|
||||
Assert.Equal(2, afterSplit.SecondaryCascade);
|
||||
Assert.InRange(afterSplit.SecondaryWeight, 0f, 0.00001f);
|
||||
Assert.True(atSplit.WithinShadowReach);
|
||||
Assert.True(afterSplit.WithinShadowReach);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CascadeSelection_StopsAtConfiguredReach()
|
||||
{
|
||||
DirectionalShadowCascadeBlend outside =
|
||||
DirectionalShadowReceiverPolicy.SelectCascade(
|
||||
100.01f,
|
||||
new Vector4(10f, 30f, 60f, 100f),
|
||||
4,
|
||||
2f);
|
||||
|
||||
Assert.False(outside.WithinShadowReach);
|
||||
Assert.Equal(3, outside.PrimaryCascade);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BiasRemainsWorldMetresAndScalesWithSurfaceSlope()
|
||||
{
|
||||
var bias = new DirectionalShadowWorldBias(0.01f, 0.04f, 0.02f);
|
||||
|
||||
Assert.Equal(0.01f, DirectionalShadowReceiverPolicy.ReceiverBiasMeters(bias, 1f), 6);
|
||||
Assert.Equal(0.05f, DirectionalShadowReceiverPolicy.ReceiverBiasMeters(bias, 0f), 6);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, false, true, true)]
|
||||
[InlineData(true, true, true, false)]
|
||||
[InlineData(true, false, false, false)]
|
||||
[InlineData(false, false, true, false)]
|
||||
internal void IndoorAndMissingDirectionalTermsNeverSample(
|
||||
bool binding,
|
||||
bool indoor,
|
||||
bool directional,
|
||||
bool expected) =>
|
||||
Assert.Equal(
|
||||
expected,
|
||||
DirectionalShadowReceiverPolicy.ShouldSample(
|
||||
binding,
|
||||
indoor,
|
||||
directional));
|
||||
|
||||
[Fact]
|
||||
public void ReceiverShadersPreserveAnimatedFoliageMaterialAndTransparencySemantics()
|
||||
{
|
||||
string root = RepositoryRoot();
|
||||
string shaderRoot = Path.Combine(
|
||||
root,
|
||||
"src", "AcDream.App", "Rendering", "Shaders");
|
||||
string vertex = File.ReadAllText(Path.Combine(shaderRoot, "mesh_atmospheric.vert"));
|
||||
string fragment = File.ReadAllText(Path.Combine(shaderRoot, "mesh_atmospheric.frag"));
|
||||
string terrain = File.ReadAllText(Path.Combine(shaderRoot, "terrain_atmospheric.frag"));
|
||||
string receiver = File.ReadAllText(Path.Combine(
|
||||
shaderRoot,
|
||||
"directional_shadow_receiver.glsl"));
|
||||
|
||||
Assert.Contains("int transformIndex = gl_BaseInstanceARB + gl_InstanceID", vertex, StringComparison.Ordinal);
|
||||
Assert.Contains("int instanceIndex = transformIndex - int(uTextureIndexB)", vertex, StringComparison.Ordinal);
|
||||
Assert.Contains("Instances[transformIndex].transform", vertex, StringComparison.Ordinal);
|
||||
Assert.Contains("instanceIndoor[instanceIndex]", vertex, StringComparison.Ordinal);
|
||||
Assert.Contains("vSelectionLighting", fragment, StringComparison.Ordinal);
|
||||
Assert.Contains("vOpacityMultiplier", fragment, StringComparison.Ordinal);
|
||||
Assert.Contains("if (color.a < 0.05) discard", fragment, StringComparison.Ordinal);
|
||||
Assert.Contains("ACDREAM_SAMPLE_ARRAY", fragment, StringComparison.Ordinal);
|
||||
Assert.Contains("combineOverlays", terrain, StringComparison.Ordinal);
|
||||
Assert.Contains("combineRoad", terrain, StringComparison.Ordinal);
|
||||
Assert.Contains("smoothstep", receiver, StringComparison.Ordinal);
|
||||
Assert.Contains("acdreamShadowBiasScale(cascade)", receiver, StringComparison.Ordinal);
|
||||
Assert.Contains("textureGather", receiver, StringComparison.Ordinal);
|
||||
Assert.Contains("acdreamShadowBilinearCompare", receiver, StringComparison.Ordinal);
|
||||
Assert.Contains("float weight = float(2 - abs(x))", receiver, StringComparison.Ordinal);
|
||||
Assert.Contains("float reachFade = 1.0 - smoothstep", receiver, StringComparison.Ordinal);
|
||||
Assert.Contains("radius = clamp(radius, 0, 2)", receiver, StringComparison.Ordinal);
|
||||
Assert.Contains("float softness = max(uShadowControl.y, 1.0)", receiver, StringComparison.Ordinal);
|
||||
|
||||
string detailVertex = File.ReadAllText(Path.Combine(
|
||||
shaderRoot,
|
||||
"mesh_detail.vert"));
|
||||
Assert.Contains("int instanceIndex = transformIndex - int(uTextureIndexB)", detailVertex, StringComparison.Ordinal);
|
||||
Assert.Contains("Instances[transformIndex].transform", detailVertex, StringComparison.Ordinal);
|
||||
Assert.Contains("instanceDetailCategory[instanceIndex]", detailVertex, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static string RepositoryRoot()
|
||||
{
|
||||
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
while (directory is not null
|
||||
&& !File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
|
||||
{
|
||||
directory = directory.Parent;
|
||||
}
|
||||
return directory?.FullName
|
||||
?? throw new InvalidOperationException("Could not locate repository root.");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue