mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-23 13:50:13 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
142 lines
3.3 KiB
C#
142 lines
3.3 KiB
C#
using Sandbox.Utility;
|
|
using System.Threading;
|
|
|
|
namespace Sandbox.Resources;
|
|
|
|
[Title( "Random Noise" )]
|
|
[Icon( "casino" )]
|
|
[ClassName( "random" )]
|
|
[Expose]
|
|
public class RandomTextureGenerator : TextureGenerator
|
|
{
|
|
public enum NoiseType
|
|
{
|
|
[Icon( "casino" )]
|
|
[Title( "Pure Random" )]
|
|
Random,
|
|
|
|
[Icon( "gradient" )]
|
|
[Title( "Perlin Noise" )]
|
|
Perlin,
|
|
|
|
[Icon( "gradient" )]
|
|
[Title( "Simplex Noise" )]
|
|
Simplex
|
|
}
|
|
|
|
public NoiseType Type { get; set; } = NoiseType.Random;
|
|
|
|
public int Seed { get; set; } = 0;
|
|
|
|
public Vector2Int Size { get; set; } = 64;
|
|
|
|
[HideIf( nameof( Type ), NoiseType.Random )]
|
|
public Vector3 Offset { get; set; } = new Vector3( 0, 0, 0 );
|
|
|
|
[HideIf( nameof( Type ), NoiseType.Random )]
|
|
public float Scale { get; set; } = 5.0f;
|
|
|
|
[Range( 1, 8 )]
|
|
[HideIf( nameof( Type ), NoiseType.Random )]
|
|
public int Octaves { get; set; } = 1;
|
|
|
|
public Gradient Gradient { get; set; } = new Gradient( new Gradient.ColorFrame( 0.0f, Color.Black ), new Gradient.ColorFrame( 1.0f, Color.White ) );
|
|
|
|
[Header( "Normal Map" ), Title( "Height to Normal" )]
|
|
public bool ConvertHeightToNormals { get; set; }
|
|
|
|
[ShowIf( nameof( ConvertHeightToNormals ), true )]
|
|
public float NormalScale { get; set; } = 1;
|
|
|
|
[Hide]
|
|
public override bool CacheToDisk => true;
|
|
|
|
protected override async ValueTask<Texture> CreateTexture( Options options, CancellationToken ct )
|
|
{
|
|
var w = Size.x.Clamp( 1, 1024 * 4 );
|
|
var h = Size.y.Clamp( 1, 1024 * 4 );
|
|
var scale = (Type != NoiseType.Random) ? Scale : 1f;
|
|
var pixels = new Color[w * h];
|
|
long seed = Seed;
|
|
INoiseField noise = null;
|
|
|
|
switch ( Type )
|
|
{
|
|
case NoiseType.Perlin:
|
|
if ( Octaves > 1 )
|
|
{
|
|
// Use fractal noise field for multiple octaves
|
|
noise = Noise.PerlinField( new Noise.FractalParameters(
|
|
Seed: Seed,
|
|
Octaves: Octaves
|
|
) );
|
|
}
|
|
else
|
|
{
|
|
noise = Noise.PerlinField( new Noise.Parameters( Seed ) );
|
|
}
|
|
break;
|
|
case NoiseType.Simplex:
|
|
if ( Octaves > 1 )
|
|
{
|
|
// Use fractal noise field for multiple octaves
|
|
noise = Noise.SimplexField( new Noise.FractalParameters(
|
|
Seed: Seed,
|
|
Octaves: Octaves
|
|
) );
|
|
}
|
|
else
|
|
{
|
|
noise = Noise.SimplexField( new Noise.Parameters( Seed ) );
|
|
}
|
|
break;
|
|
default:
|
|
seed = (long)(IntToRandomFloat( Seed ) * int.MaxValue);
|
|
break;
|
|
}
|
|
|
|
await Sandbox.Utility.Parallel.ForAsync( 0, w * h, ct, ( i, t ) =>
|
|
{
|
|
var x = i % w;
|
|
var y = i / w;
|
|
var noiseValue = 0f;
|
|
if ( noise is not null )
|
|
{
|
|
noiseValue = noise.Sample( (x + Offset.x) * scale, (y + Offset.y) * scale, Offset.z * scale );
|
|
}
|
|
else
|
|
{
|
|
noiseValue = IntToRandomFloat( seed + i );
|
|
}
|
|
pixels[i] = Gradient.Evaluate( noiseValue );
|
|
return ValueTask.CompletedTask;
|
|
} );
|
|
|
|
var bitmap = new Bitmap( w, h, false );
|
|
bitmap.SetPixels( pixels );
|
|
|
|
if ( ConvertHeightToNormals )
|
|
{
|
|
bitmap = bitmap.HeightmapToNormalMap( NormalScale );
|
|
}
|
|
|
|
ct.ThrowIfCancellationRequested();
|
|
|
|
return bitmap.ToTexture();
|
|
}
|
|
|
|
public static float IntToRandomFloat( long seed )
|
|
{
|
|
unchecked
|
|
{
|
|
// Multiply the seed by a large prime number
|
|
seed = (seed ^ 0x6D2B79F5) * 0x1B873593;
|
|
seed = (seed ^ (seed >> 13)) * 0x85EBCA6B;
|
|
seed = seed ^ (seed >> 16);
|
|
|
|
// Normalize to a float in the range [0, 1)
|
|
return (seed & 0x7FFFFFFF) / (float)int.MaxValue;
|
|
}
|
|
}
|
|
}
|