/// <summary> /// Generates a toroidally tiled noise /// </summary> private static unsafe void GenerateNoise( Texture3dData data, Noise3dTextureBuilderParameters parameters, byte* voxels ) { SimpleNoise3d sNoise = new SimpleNoise3d(); Noise noise = new Noise( ); float nW = parameters.NoiseWidth; float nH = parameters.NoiseHeight; float nD = parameters.NoiseDepth; float nX0 = parameters.NoiseX; float nY0 = parameters.NoiseY; float nZ0 = parameters.NoiseZ; float nXInc = nW / data.Width; float nYInc = nH / data.Height; float nZInc = nD / data.Depth; byte* voxel = voxels; int bytesPerVoxel = TextureFormatInfo.GetSizeInBytes( parameters.Format ); if ( bytesPerVoxel != 3 && bytesPerVoxel != 4 ) { throw new InvalidDataException( string.Format( "Unexpected voxel stride of {0} - expected either 3 or 4 from format {1}", bytesPerVoxel, parameters.Format ) ); } // Check hacked channel expectations... bool hasAlpha = TextureFormatInfo.HasAlphaChannel( parameters.Format ); float nZ = nZ0; float maxNoise = float.MinValue; float minNoise = float.MaxValue; for ( int z = 0; z < parameters.Depth; ++z, nZ += nZInc ) { float nY = nY0; for ( int y = 0; y < parameters.Height; ++y, nY += nYInc ) { float nX = nX0; for ( int x = 0; x < parameters.Width; ++x, nX += nXInc ) { switch ( parameters.GenerationType ) { case NoiseGenerationType.Grayscale : { float n = ( 1.0f + sNoise.GetTilingNoise( nX, nY, nZ, nW, nH, nD ) ) / 2; maxNoise = Math.Max( maxNoise, n ); minNoise = Math.Min( minNoise, n ); // float n = 0.5f + noise.GetNoise( nX, nY, nZ ); voxel[ 0 ] = NoiseToByte( n ); voxel[ 1 ] = voxel[ 0 ]; voxel[ 2 ] = voxel[ 0 ]; if ( hasAlpha ) { voxel[ 3 ] = voxel[ 0 ]; } break; } case NoiseGenerationType.MultiChannel : { float r = noise.GetNoise( nX, nY, nZ ); float g = noise.GetNoise( nX + nW, nY, nZ ); float b = noise.GetNoise( nX, nY + nH, nZ ); voxel[ 0 ] = NoiseToByte( r ); voxel[ 1 ] = NoiseToByte( g ); voxel[ 2 ] = NoiseToByte( b ); if ( hasAlpha ) { float a = noise.GetNoise( nX, nY, nZ + parameters.NoiseDepth ); voxel[ 3 ] = NoiseToByte( a ); } break; } case NoiseGenerationType.TilingGrayscale : { float n = GetTiledNoise( noise, nX, nY, nZ, nX0, nY0, nZ0, nW, nH, nD ); voxel[ 0 ] = NoiseToByte( n ); voxel[ 1 ] = voxel[ 0 ]; voxel[ 2 ] = voxel[ 0 ]; if ( hasAlpha ) { voxel[ 3 ] = voxel[ 0 ]; } break; } case NoiseGenerationType.TilingMultiChannel : { float r = GetTiledNoise( noise, nX, nY, nZ, nX0, nY0, nZ0, nW, nH, nD ); float g = GetTiledNoise( noise, nX + nW, nY, nZ, nX0 + nW, nY0, nZ0, nW, nH, nD ); float b = GetTiledNoise( noise, nX, nY + nH, nZ, nX0, nY0 + nH, nZ0, nW, nH, nD ); voxel[ 0 ] = NoiseToByte( r ); voxel[ 1 ] = NoiseToByte( g ); voxel[ 2 ] = NoiseToByte( b ); if ( hasAlpha ) { float a = GetTiledNoise( noise, nX, nY, nZ + nD, nX0, nY0, nZ0 + nD, nW, nH, nD ); voxel[ 3 ] = NoiseToByte( a ); } break; } case NoiseGenerationType.BigNoise : { float real = 0.5f + GetTiledNoise( noise, nX, nY, nZ, nX0, nY0, nZ0, nW, nH, nD ); float imag = 0.5f + GetTiledNoise( noise, nX + nW, nY + nH, nZ + nD, nX0, nY0, nZ0, nW, nH, nD ); // maxNoise = Math.Max( maxNoise, real ); // minNoise = Math.Min( minNoise, real ); double a = Math.PI + Math.PI * real; voxel[ 0 ] = NoiseToByte( real ); voxel[ 1 ] = NoiseToByte( imag ); voxel[ 2 ] = ( byte )Utils.Clamp( ( Math.Sin( a ) + 1 ) * 127.5, 0, 255 ); voxel[ 3 ] = ( byte )Utils.Clamp( ( Math.Cos( a ) + 1 ) * 127.5, 0, 255 ); break; } default : throw new NotSupportedException( string.Format( "Noise generation type \"{0}\" is not supported yet", parameters.GenerationType ) ); } voxel += bytesPerVoxel; } } } }
private static float GetNoise( Noise noise, float w, float h, float d, float x, float y, float z ) { return noise.GetNoise( x % w, y % h, z % d ); }