Skip to content

Commit a84379e

Browse files
committed
Added cellular size jitter
1 parent 8656759 commit a84379e

File tree

4 files changed

+148
-27
lines changed

4 files changed

+148
-27
lines changed

include/FastNoise/Generators/Cellular.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ namespace FastNoise
1414
void SetMinkowskiP( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mMinkowskiP, gen ); }
1515
void SetMinkowskiP( float value ) { mMinkowskiP = value; }
1616

17-
void SetJitterModifier( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mJitterModifier, gen ); }
18-
void SetJitterModifier( float value ) { mJitterModifier = value; }
17+
void SetGridJitter( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mGridJitter, gen ); }
18+
void SetGridJitter( float value ) { mGridJitter = value; }
1919

20+
void SetSizeJitter( SmartNodeArg<> gen ) { this->SetSourceMemberVariable( mSizeJitter, gen ); }
21+
void SetSizeJitter( float value ) { mSizeJitter = value; }
2022
protected:
2123
HybridSource mMinkowskiP = 1.5f;
22-
HybridSource mJitterModifier = 1.0f;
24+
HybridSource mGridJitter = 1.0f;
25+
HybridSource mSizeJitter = 0.f;
2326
DistanceFunction mDistanceFunction = DistanceFunction::EuclideanSquared;
2427
};
2528

@@ -30,11 +33,24 @@ namespace FastNoise
3033
MetadataT()
3134
{
3235
this->groups.push_back( "Coherent Noise" );
33-
this->AddVariableEnum( { "Distance Function", "How distance to closest cells is calculated\nHybrid is EuclideanSquared + Manhattan" },
36+
this->AddVariableEnum( { "Distance Function", "How distance to closest cells is calculated\n"
37+
"Hybrid is EuclideanSquared + Manhattan" },
3438
DistanceFunction::EuclideanSquared, &Cellular<PARENT>::SetDistanceFunction, kDistanceFunction_Strings );
35-
this->AddHybridSource( { "Minkowski P", "Only affects Minkowski distance function\n1 = Manhattan\n2 = Euclidean" }, 1.5f, &Cellular<PARENT>::SetMinkowskiP, &Cellular<PARENT>::SetMinkowskiP );
3639

37-
this->AddHybridSource( { "Jitter Modifier", "Above 1.0 will cause grid artifacts\n0.0 will output a uniform grid" }, 1.0f, &Cellular<PARENT>::SetJitterModifier, &Cellular<PARENT>::SetJitterModifier );
40+
this->AddHybridSource( { "Minkowski P", "Only affects Minkowski distance function\n"
41+
"1 = Manhattan\n"
42+
"2 = Euclidean" },
43+
1.5f, &Cellular<PARENT>::SetMinkowskiP, &Cellular<PARENT>::SetMinkowskiP );
44+
45+
this->AddHybridSource( { "Grid Jitter", "How much to displace cells from their uniform grid position\n"
46+
"0.0 will output a uniform grid\n"
47+
"Above 1.0 will cause grid artifacts" },
48+
1.0f, &Cellular<PARENT>::SetGridJitter, &Cellular<PARENT>::SetGridJitter );
49+
50+
this->AddHybridSource( { "Size Jitter", "Apply a random multiplier each cell's distance calculation\n"
51+
"Causes more variation in cell size\n"
52+
"Can cause grid artifacts" },
53+
0.0f, &Cellular<PARENT>::SetSizeJitter, &Cellular<PARENT>::SetSizeJitter );
3854
}
3955
};
4056
#endif

include/FastNoise/Generators/Cellular.inl

Lines changed: 124 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
1919
{
2020
float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y ) const
2121
{
22-
float32v jitter = float32v( this->kJitter2D ) * this->GetSourceValue( mJitterModifier, seed, x, y );
22+
float32v jitter = float32v( this->kJitter2D ) * this->GetSourceValue( mGridJitter, seed, x, y );
23+
float32v sizeJitter;
24+
bool sizeJitterActive = mSizeJitter.simdGeneratorPtr || mSizeJitter.constant != 0.0f;
25+
if( sizeJitterActive )
26+
{
27+
sizeJitter = this->GetSourceValue( mSizeJitter, seed, x, y ) * float32v( -1.f / 0x3ff );
28+
}
29+
2330
std::array<int32v, kMaxDistanceCount> valueHash;
2431
std::array<float32v, kMaxDistanceCount> distance;
2532

@@ -43,15 +50,20 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
4350
for( int yi = 0; yi < 3; yi++ )
4451
{
4552
int32v hash = HashPrimesHB( seed, xc, yc );
46-
float32v xd = FS::Convert<float>( hash & int32v( 0xffff ) ) - float32v( 0xffff / 2.0f );
47-
float32v yd = FS::Convert<float>( FS::BitShiftRightZeroExtend( hash, 16 ) ) - float32v( 0xffff / 2.0f );
53+
float32v xd = FS::Convert<float>( hash & int32v( 0x7ff ) ) - float32v( 0x7ff / 2.0f );
54+
float32v yd = FS::Convert<float>( FS::BitShiftRightZeroExtend( hash, 21 ) ) - float32v( 0x7ff / 2.0f );
4855

4956
float32v invMag = jitter * FS::InvSqrt( FS::FMulAdd( xd, xd, yd * yd ) );
5057
xd = FS::FMulAdd( xd, invMag, xcf );
5158
yd = FS::FMulAdd( yd, invMag, ycf );
5259

5360
int32v newCellValueHash = hash;
54-
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd );
61+
float32v newDistance = CalcDistance<true>( mDistanceFunction, mMinkowskiP, seed, xd, yd );
62+
if( sizeJitterActive )
63+
{
64+
float32v distanceJitter = FS::Convert<float>( ( hash >> 11 ) & int32v( 0x3ff ) );
65+
newDistance *= FS::FNMulAdd( sizeJitter, distanceJitter, float32v( 1 ) );
66+
}
5567

5668
for( int i = 0; ; i++ )
5769
{
@@ -63,7 +75,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
6375
distance[i] = FS::Select( closer, newDistance, distance[i] );
6476
valueHash[i] = FS::Select( closer, newCellValueHash, valueHash[i] );
6577

66-
if( i > mValueIndex )
78+
if( i >= mValueIndex )
6779
{
6880
break;
6981
}
@@ -84,7 +96,14 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
8496

8597
float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z ) const
8698
{
87-
float32v jitter = float32v( this->kJitter3D ) * this->GetSourceValue( mJitterModifier, seed, x, y, z );
99+
float32v jitter = float32v( this->kJitter3D ) * this->GetSourceValue( mGridJitter, seed, x, y, z );
100+
float32v sizeJitter;
101+
bool sizeJitterActive = mSizeJitter.simdGeneratorPtr || mSizeJitter.constant != 0.0f;
102+
if( sizeJitterActive )
103+
{
104+
sizeJitter = this->GetSourceValue( mSizeJitter, seed, x, y, z ) * float32v( -1.f / 0xffff );
105+
}
106+
88107
std::array<int32v, kMaxDistanceCount> valueHash;
89108
std::array<float32v, kMaxDistanceCount> distance;
90109

@@ -126,6 +145,11 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
126145

127146
int32v newCellValueHash = hash;
128147
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd );
148+
if( sizeJitterActive )
149+
{
150+
float32v distanceJitter = FS::Convert<float>( hash & int32v( 0xffff ) );
151+
newDistance *= FS::FNMulAdd( sizeJitter, distanceJitter, float32v( 1 ) );
152+
}
129153

130154
for( int i = 0; ; i++ )
131155
{
@@ -137,7 +161,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
137161
distance[i] = FS::Select( closer, newDistance, distance[i] );
138162
valueHash[i] = FS::Select( closer, newCellValueHash, valueHash[i] );
139163

140-
if( i > mValueIndex )
164+
if( i >= mValueIndex )
141165
{
142166
break;
143167
}
@@ -161,7 +185,14 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
161185

162186
float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z , float32v w ) const
163187
{
164-
float32v jitter = float32v( this->kJitter4D ) * this->GetSourceValue( mJitterModifier, seed, x, y, z, w );
188+
float32v jitter = float32v( this->kJitter4D ) * this->GetSourceValue( mGridJitter, seed, x, y, z, w );
189+
float32v sizeJitter;
190+
bool sizeJitterActive = mSizeJitter.simdGeneratorPtr || mSizeJitter.constant != 0.0f;
191+
if( sizeJitterActive )
192+
{
193+
sizeJitter = this->GetSourceValue( mSizeJitter, seed, x, y, z, w ) * float32v( -1.f / 0xfffff );
194+
}
195+
165196
std::array<int32v, kMaxDistanceCount> valueHash;
166197
std::array<float32v, kMaxDistanceCount> distance;
167198

@@ -212,6 +243,11 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
212243

213244
int32v newCellValueHash = hash;
214245
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd, wd );
246+
if( sizeJitterActive )
247+
{
248+
float32v distanceJitter = FS::Convert<float>( hash & int32v( 0xfffff ) );
249+
newDistance *= FS::FNMulAdd( sizeJitter, distanceJitter, float32v( 1 ) );
250+
}
215251

216252
for( int i = 0; ; i++ )
217253
{
@@ -223,7 +259,7 @@ class FastSIMD::DispatchClass<FastNoise::CellularValue, SIMD> final : public vir
223259
distance[i] = FS::Select( closer, newDistance, distance[i] );
224260
valueHash[i] = FS::Select( closer, newCellValueHash, valueHash[i] );
225261

226-
if( i > mValueIndex )
262+
if( i >= mValueIndex )
227263
{
228264
break;
229265
}
@@ -254,7 +290,13 @@ class FastSIMD::DispatchClass<FastNoise::CellularDistance, SIMD> final : public
254290
{
255291
float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y ) const
256292
{
257-
float32v jitter = float32v( this->kJitter2D ) * this->GetSourceValue( mJitterModifier, seed, x, y );
293+
float32v jitter = float32v( this->kJitter2D ) * this->GetSourceValue( mGridJitter, seed, x, y );
294+
float32v sizeJitter;
295+
bool sizeJitterActive = mSizeJitter.simdGeneratorPtr || mSizeJitter.constant != 0.0f;
296+
if( sizeJitterActive )
297+
{
298+
sizeJitter = this->GetSourceValue( mSizeJitter, seed, x, y ) * float32v( -1.f / 0x3ff );
299+
}
258300

259301
std::array<float32v, kMaxDistanceCount> distance;
260302
distance.fill( float32v( kInfinity ) );
@@ -278,14 +320,19 @@ class FastSIMD::DispatchClass<FastNoise::CellularDistance, SIMD> final : public
278320
for ( int yi = 0; yi < 3; yi++ )
279321
{
280322
int32v hash = HashPrimesHB( seed, xc, yc );
281-
float32v xd = FS::Convert<float>( hash & int32v( 0xffff ) ) - float32v( 0xffff / 2.0f );
282-
float32v yd = FS::Convert<float>( FS::BitShiftRightZeroExtend( hash, 16 ) ) - float32v( 0xffff / 2.0f );
323+
float32v xd = FS::Convert<float>( hash & int32v( 0x7ff ) ) - float32v( 0x7ff / 2.0f );
324+
float32v yd = FS::Convert<float>( FS::BitShiftRightZeroExtend( hash, 21 ) ) - float32v( 0x7ff / 2.0f );
283325

284326
float32v invMag = jitter * FS::InvSqrt( FS::FMulAdd( xd, xd, yd * yd ) );
285327
xd = FS::FMulAdd( xd, invMag, xcfOffset );
286328
yd = FS::FMulAdd( yd, invMag, ycf - y );
287329

288330
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd );
331+
if( sizeJitterActive )
332+
{
333+
float32v distanceJitter = FS::Convert<float>( ( hash >> 11 ) & int32v( 0x3ff ) );
334+
newDistance *= FS::FNMulAdd( sizeJitter, distanceJitter, float32v( 1 ) );
335+
}
289336

290337
for( int i = kMaxDistanceCount - 1; i > 0; i-- )
291338
{
@@ -306,7 +353,13 @@ class FastSIMD::DispatchClass<FastNoise::CellularDistance, SIMD> final : public
306353

307354
float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z ) const
308355
{
309-
float32v jitter = float32v( this->kJitter3D ) * this->GetSourceValue( mJitterModifier, seed, x, y, z );
356+
float32v jitter = float32v( this->kJitter3D ) * this->GetSourceValue( mGridJitter, seed, x, y, z );
357+
float32v sizeJitter;
358+
bool sizeJitterActive = mSizeJitter.simdGeneratorPtr || mSizeJitter.constant != 0.0f;
359+
if( sizeJitterActive )
360+
{
361+
sizeJitter = this->GetSourceValue( mSizeJitter, seed, x, y, z ) * float32v( -1.f / 0xffff );
362+
}
310363

311364
std::array<float32v, kMaxDistanceCount> distance;
312365
distance.fill( float32v( kInfinity ) );
@@ -348,6 +401,11 @@ class FastSIMD::DispatchClass<FastNoise::CellularDistance, SIMD> final : public
348401
zd = FS::FMulAdd( zd, invMag, zcf - z );
349402

350403
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd );
404+
if( sizeJitterActive )
405+
{
406+
float32v distanceJitter = FS::Convert<float>( hash & int32v( 0xffff ) );
407+
newDistance *= FS::FNMulAdd( sizeJitter, distanceJitter, float32v( 1 ) );
408+
}
351409

352410
for( int i = kMaxDistanceCount - 1; i > 0; i-- )
353411
{
@@ -371,7 +429,13 @@ class FastSIMD::DispatchClass<FastNoise::CellularDistance, SIMD> final : public
371429

372430
float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z, float32v w ) const
373431
{
374-
float32v jitter = float32v( this->kJitter4D ) * this->GetSourceValue( mJitterModifier, seed, x, y, z, w );
432+
float32v jitter = float32v( this->kJitter4D ) * this->GetSourceValue( mGridJitter, seed, x, y, z, w );
433+
float32v sizeJitter;
434+
bool sizeJitterActive = mSizeJitter.simdGeneratorPtr || mSizeJitter.constant != 0.0f;
435+
if( sizeJitterActive )
436+
{
437+
sizeJitter = this->GetSourceValue( mSizeJitter, seed, x, y, z, w ) * float32v( -1.f / 0xfffff );
438+
}
375439

376440
std::array<float32v, kMaxDistanceCount> distance;
377441
distance.fill( float32v( kInfinity ) );
@@ -423,6 +487,11 @@ class FastSIMD::DispatchClass<FastNoise::CellularDistance, SIMD> final : public
423487
wd = FS::FMulAdd( wd, invMag, wcf - w );
424488

425489
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd, wd );
490+
if( sizeJitterActive )
491+
{
492+
float32v distanceJitter = FS::Convert<float>( hash & int32v( 0xfffff ) );
493+
newDistance *= FS::FNMulAdd( sizeJitter, distanceJitter, float32v( 1 ) );
494+
}
426495

427496
for( int i = kMaxDistanceCount - 1; i > 0; i-- )
428497
{
@@ -489,7 +558,14 @@ class FastSIMD::DispatchClass<FastNoise::CellularLookup, SIMD> final : public vi
489558
{
490559
float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y ) const
491560
{
492-
float32v jitter = float32v( this->kJitter2D ) * this->GetSourceValue( mJitterModifier, seed, x, y );
561+
float32v jitter = float32v( this->kJitter2D ) * this->GetSourceValue( mGridJitter, seed, x, y );
562+
float32v sizeJitter;
563+
bool sizeJitterActive = mSizeJitter.simdGeneratorPtr || mSizeJitter.constant != 0.0f;
564+
if( sizeJitterActive )
565+
{
566+
sizeJitter = this->GetSourceValue( mSizeJitter, seed, x, y ) * float32v( -1.f / 0x3ff );
567+
}
568+
493569
float32v distance( FLT_MAX );
494570
float32v cellX, cellY;
495571

@@ -511,8 +587,8 @@ class FastSIMD::DispatchClass<FastNoise::CellularLookup, SIMD> final : public vi
511587
for( int yi = 0; yi < 3; yi++ )
512588
{
513589
int32v hash = HashPrimesHB( seed, xc, yc );
514-
float32v xd = FS::Convert<float>( hash & int32v( 0xffff ) ) - float32v( 0xffff / 2.0f );
515-
float32v yd = FS::Convert<float>( FS::BitShiftRightZeroExtend( hash, 16 ) ) - float32v( 0xffff / 2.0f );
590+
float32v xd = FS::Convert<float>( hash & int32v( 0x7ff ) ) - float32v( 0x7ff / 2.0f );
591+
float32v yd = FS::Convert<float>( FS::BitShiftRightZeroExtend( hash, 21 ) ) - float32v( 0x7ff / 2.0f );
516592

517593
float32v invMag = jitter * FS::InvSqrt( FS::FMulAdd( xd, xd, yd * yd ) );
518594
float32v localCellX = FS::FMulAdd( xd, invMag, xcf );
@@ -521,6 +597,11 @@ class FastSIMD::DispatchClass<FastNoise::CellularLookup, SIMD> final : public vi
521597
yd = localCellY - y;
522598

523599
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd );
600+
if( sizeJitterActive )
601+
{
602+
float32v distanceJitter = FS::Convert<float>( ( hash >> 11 ) & int32v( 0x3ff ) );
603+
newDistance *= FS::FNMulAdd( sizeJitter, distanceJitter, float32v( 1 ) );
604+
}
524605

525606
mask32v closer = newDistance < distance;
526607
distance = FS::Min( newDistance, distance );
@@ -540,7 +621,14 @@ class FastSIMD::DispatchClass<FastNoise::CellularLookup, SIMD> final : public vi
540621

541622
float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z ) const
542623
{
543-
float32v jitter = float32v( this->kJitter3D ) * this->GetSourceValue( mJitterModifier, seed, x, y, z );
624+
float32v jitter = float32v( this->kJitter3D ) * this->GetSourceValue( mGridJitter, seed, x, y, z );
625+
float32v sizeJitter;
626+
bool sizeJitterActive = mSizeJitter.simdGeneratorPtr || mSizeJitter.constant != 0.0f;
627+
if( sizeJitterActive )
628+
{
629+
sizeJitter = this->GetSourceValue( mSizeJitter, seed, x, y, z ) * float32v( -1.f / 0xffff );
630+
}
631+
544632
float32v distance( FLT_MAX );
545633
float32v cellX, cellY, cellZ;
546634

@@ -582,6 +670,11 @@ class FastSIMD::DispatchClass<FastNoise::CellularLookup, SIMD> final : public vi
582670
zd = localCellZ - z;
583671

584672
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd );
673+
if( sizeJitterActive )
674+
{
675+
float32v distanceJitter = FS::Convert<float>( hash & int32v( 0xffff ) );
676+
newDistance *= FS::FNMulAdd( sizeJitter, distanceJitter, float32v( 1 ) );
677+
}
585678

586679
mask32v closer = newDistance < distance;
587680
distance = FS::Min( newDistance, distance );
@@ -605,7 +698,14 @@ class FastSIMD::DispatchClass<FastNoise::CellularLookup, SIMD> final : public vi
605698

606699
float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z, float32v w ) const
607700
{
608-
float32v jitter = float32v( this->kJitter4D ) * this->GetSourceValue( mJitterModifier, seed, x, y, z, w );
701+
float32v jitter = float32v( this->kJitter4D ) * this->GetSourceValue( mGridJitter, seed, x, y, z, w );
702+
float32v sizeJitter;
703+
bool sizeJitterActive = mSizeJitter.simdGeneratorPtr || mSizeJitter.constant != 0.0f;
704+
if( sizeJitterActive )
705+
{
706+
sizeJitter = this->GetSourceValue( mSizeJitter, seed, x, y, z, w ) * float32v( -1.f / 0xfffff );
707+
}
708+
609709
float32v distance( FLT_MAX );
610710
float32v cellX, cellY, cellZ, cellW;
611711

@@ -657,6 +757,11 @@ class FastSIMD::DispatchClass<FastNoise::CellularLookup, SIMD> final : public vi
657757
wd = localCellW - w;
658758

659759
float32v newDistance = CalcDistance<false>( mDistanceFunction, mMinkowskiP, seed, xd, yd, zd, wd );
760+
if( sizeJitterActive )
761+
{
762+
float32v distanceJitter = FS::Convert<float>( hash & int32v( 0xfffff ) );
763+
newDistance *= FS::FNMulAdd( sizeJitter, distanceJitter, float32v( 1 ) );
764+
}
660765

661766
mask32v closer = newDistance < distance;
662767
distance = FS::Min( newDistance, distance );

0 commit comments

Comments
 (0)