Effects/PerlinVolumeTexture.cs
using System;
using Sandbox.Utility;
/// <summary>
/// Procedurally builds a 3‑dimensional Perlin noise volume texture for use in materials and shaders.
/// </summary>
public sealed class PerlinVolumeTexture
{
/// <summary>Width of the 3D texture in voxels.</summary>
public int Width { get; }
/// <summary>Height of the 3D texture in voxels.</summary>
public int Height { get; }
/// <summary>Depth of the 3D texture in voxels.</summary>
public int Depth { get; }
/// <summary>
/// Spatial scale applied to the noise coordinates. Higher values zoom out; lower values zoom in.
/// </summary>
public float Scale { get; set; } = 1.0f;
/// <summary>Number of Fractal Brownian Motion octaves layered together.</summary>
public int Octaves { get; set; } = 4;
/// <summary>Resource name given to the resulting <see cref="Texture"/>.</summary>
public string Name { get; set; }
/// <summary>
/// Creates a new Perlin 3D texture generator.
/// </summary>
public PerlinVolumeTexture( int width, int height, int depth, string name = null )
{
if ( width <= 0 || height <= 0 || depth <= 0 )
throw new ArgumentOutOfRangeException( "Texture dimensions must be positive non‑zero." );
Width = width;
Height = height;
Depth = depth;
Name = name ?? $"perlin_volume_{width}x{height}x{depth}";
}
/// <summary>
/// Generates the noise on the CPU and uploads the data to a GPU.
/// </summary>
public Texture Generate()
{
var buffer = new byte[Width * Height * Depth];
var idx = 0;
for ( int z = 0; z < Depth; z++ )
{
for ( int y = 0; y < Height; y++ )
{
for ( int x = 0; x < Width; x++ )
{
// Noise.Fbm returns [0,1]. Convert to byte range.
float n = Noise.Fbm( Octaves, x * Scale, y * Scale, z * Scale );
buffer[idx++] = (byte)(n * 255f);
}
}
}
return Texture.CreateVolume( Width, Height, Depth, ImageFormat.I8 )
.WithName( Name )
.WithData( buffer )
.Finish();
}
}