Code/GaussianNoiseGenerator.cs
using System;

namespace Sandbox;

public class GaussianNoiseGenerator
{
    private Random random;

    public GaussianNoiseGenerator(int? seed = null)
    {
        random = seed.HasValue ? new Random(seed.Value) : new Random();
    }

    public Texture CreateNoiseTexture(int resolution)
    {
        // Calculate the total number of floats needed (4 per pixel for RGBA format)
        int totalFloats = resolution * resolution * 4;
        float[] noiseData = new float[totalFloats];

        // Generate noise for each pixel
        for (int y = 0; y < resolution; y++)
        {
            for (int x = 0; x < resolution; x++)
            {
                int pixelIndex = (y * resolution + x) * 4;

                // Generate two pairs of independent Gaussian values
                var (z0, z1) = GenerateGaussianPair();
                var (z2, z3) = GenerateGaussianPair();

                // Store the values directly without clamping
                noiseData[pixelIndex] = z0;     // R channel
                noiseData[pixelIndex + 1] = z1; // G channel
                noiseData[pixelIndex + 2] = z2; // B channel
                noiseData[pixelIndex + 3] = z3; // A channel
            }
        }

        // Convert float array to byte array for the texture builder
        byte[] byteData = new byte[totalFloats * sizeof(float)];
        Buffer.BlockCopy(noiseData, 0, byteData, 0, byteData.Length);

        return Texture.Create(resolution, resolution)
            .WithUAVBinding()
            .WithFormat(ImageFormat.RGBA32323232F)
            .WithData(byteData, byteData.Length)
            .Finish();
    }

    /// <summary>
    /// Generates a pair of independent Gaussian-distributed random values using the Box-Muller transform
    /// </summary>
    private (float z0, float z1) GenerateGaussianPair()
    {
        // Ensure u1 is never exactly 0 to avoid log(0)
        float u1 = Math.Max(float.Epsilon, (float)random.NextDouble());
        float u2 = (float)random.NextDouble();
        
        float magnitude = (float)Math.Sqrt(-2.0f * Math.Log(u1));
        float angle = (float)(2.0f * Math.PI * u2);
        
        // Generate two independent standard normal variables
        float z0 = magnitude * (float)Math.Cos(angle);
        float z1 = magnitude * (float)Math.Sin(angle);
        
        return (z0, z1);
    }
}