Aetheria/Assets/Scripts/ServerShared/GravityShader.cs
Meta Vens 9b1b27d2d6 GravityShader: verbatim string, not a raw string literal (Unity's C# 9)
Commit 13c7a087 and the merge a1b54bea do not build: error CS8773, raw string literals need C# 11.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:47:01 +02:00

63 lines
2.5 KiB
C#

using System.Globalization;
/// <summary>
/// The single author of Assets/Shaders/Gravity.cginc, the GPU lowering of the zone's potential. The law is
/// GravityField's (its constants are read here, not respelled) and the height is Zone.GetHeight: each well's
/// potential minus its reference, summed, divided by the exaggeration. Unity does not run C# when it imports a
/// shader, so the committed cginc is this output; GravityShaderTests fails unless it equals Source() exactly.
/// To change the shader, change this file and regenerate: AETHERIA_REGENERATE_GRAVITY_CGINC=1 dotnet test --filter GravityShaderTests.
/// </summary>
public static class GravityShader
{
public const string Path = "Assets/Shaders/Gravity.cginc";
/// <summary>The whole file, with LF line ends.</summary>
public static string Source() => (Template
.Replace("@TAIL@", GravityField.TailOffset.ToString("R", CultureInfo.InvariantCulture)))
.Replace("\r\n", "\n");
private const string Template = @"#ifndef AETHERIA_GRAVITY_INCLUDED
#define AETHERIA_GRAVITY_INCLUDED
// GENERATED by ServerShared/GravityShader.cs from GravityField; do not edit (GravityShaderTests fails on any difference).
// The lowering of the zone's potential (aetheria-gravity, cut grid-lowering). The law is ServerShared's GravityField
// and the height is Zone.GetHeight; this file decides nothing. GravityLowering.Lower fills the buffer and the globals
// from the zone (positions from Orbit.Position, reference from Zone.WellReference) each frame.
// GravityFieldParityVerify renders it and compares every texel with -Zone.GetHeight.
struct GravityWell
{
float2 position;
float strength;
float coreRadius;
float reference;
};
StructuredBuffer<GravityWell> _GravityWells;
int _GravityWellCount;
float _HeightExaggeration;
// GravityField.Potential: c is the well's strength, R its core radius, r the distance.
float gravityPotential(float c, float R, float r)
{
return c == 0 ? 0 :
r < R
? c * r * r / (2 * R * R)
: c * (log(r / R) + @TAIL@);
}
// Zone.GetHeight at world xz: each well's potential minus its own reference, summed, divided by the exaggeration.
float gravityHeight(float2 p)
{
float result = 0;
for (int i = 0; i < _GravityWellCount; i++)
{
GravityWell well = _GravityWells[i];
result += gravityPotential(well.strength, well.coreRadius, length(p - well.position)) - well.reference;
}
return result / _HeightExaggeration;
}
#endif
";
}