# Thread: I actually managed to figure out cellular noise

1. ## I actually managed to figure out cellular noise

I wanted to see if I could figure out a cellular noise node before reading up on the Worley algorithm (which gives more interesting results, IMHO). Took me a whole freakin' day, but I got there.

The hard part is going to be implementing bump vector generation without absolutely killing render times.

2. Did some refactoring, and also tried an LCG random-number generator, but it gave artifacty results compared to using the simplex noise for the coordinate distortion routine. A Worley cellular noise node will definitely be faster, but this one works out pretty well visually, especially when using a lot of octaves (which is where using the LCG rng directly tended to fail).

Code:
```//
//  Cellular_Noise.cpp
//  RainyBrain_Nodes
//
//  E-Mail: [email protected]
//  Public Domain, Zero Restrictions
//

// ============================================================================ Standard Includes
// Standard Includes
// ----------------------------------------------------------------------------
#include <cmath>

// ============================================================================ RainyBrain Includes
// RainyBrain Includes
// ----------------------------------------------------------------------------
#include "../Types/LWTypes.h"

#include "Cellular_Noise.h"

namespace Noise
{
// ======================================================================== Noise Generators
// Noise Generators
// ------------------------------------------------------------------------ Generate (3D)
Cellular_Result Cellular::Generate( const double x,
const double y,
const double z )
{
// Construct points representing the corners of
// a 3x3 integer box region surrounding the incoming
// point.
LWTypes::LWDVector corners[64];

const double x_floor = std::floor(x);
const double y_floor = std::floor(y);
const double z_floor = std::floor(z);

const double x_ceil  = std::ceil (x);
const double y_ceil  = std::ceil (y);
const double z_ceil  = std::ceil (z);

const double x_coords[4] = { x_floor - 1.0, x_floor, x_ceil, x_ceil + 1.0 };
const double y_coords[4] = { y_floor - 1.0, y_floor, y_ceil, y_ceil + 1.0 };
const double z_coords[4] = { z_floor - 1.0, z_floor, z_ceil, z_ceil + 1.0 };

for ( int ix = 0, icorner = 0; ix < 4; ++ix )
for ( int iy = 0; iy < 4; ++iy, icorner += 4 )
{
corners[ icorner     ] = LWTypes::LWDVector( x_coords[ix], y_coords[iy], z_coords[0] );
corners[ icorner + 1 ] = LWTypes::LWDVector( x_coords[ix], y_coords[iy], z_coords[1] );
corners[ icorner + 2 ] = LWTypes::LWDVector( x_coords[ix], y_coords[iy], z_coords[2] );
corners[ icorner + 3 ] = LWTypes::LWDVector( x_coords[ix], y_coords[iy], z_coords[3] );
}

// Create set of distorted corner points deviating at
// most 0.5 units from the original coordinate.
LWTypes::LWDVector distorted_corners[64];

auto Distort_Point = [&](LWTypes::LWDVector point) -> LWTypes::LWDVector
{
const Noise::Simplex_Result simplex_noise( Noise::Simplex::Generate( point.X(), point.Y(), point.Z() ) );

return LWTypes::LWDVector ( point.X() + simplex_noise.Noise_dX * 0.25,
point.Y() + simplex_noise.Noise_dY * 0.25,
point.Z() + simplex_noise.Noise_dZ * 0.25 );
};

for ( unsigned i = 0; i < 64; ++i )
distorted_corners[i] = Distort_Point( corners[i] );

// Find distorted corner closest to incoming point
const LWTypes::LWDVector xyz_prime( x, y, z );

unsigned closest_corner_index     = 0;
double   closest_distance_squared = Math::Distance_Squared( xyz_prime, distorted_corners[0] );

for ( unsigned   current_corner_index = 1;
current_corner_index < 64;
++current_corner_index)
{
const double distorted_distance_squared = Math::Distance_Squared( xyz_prime, distorted_corners[current_corner_index] );

if ( distorted_distance_squared < closest_distance_squared )
{
closest_corner_index     = current_corner_index;
closest_distance_squared = distorted_distance_squared;
}
}

// Return distance scaled to [-1, 1] and region
const double             downsample     ( 0.625 );
const LWTypes::LWDVector closest_corner ( distorted_corners[closest_corner_index] );

return Cellular_Result( (closest_distance_squared * downsample * 2.0) - 1.0,
Noise::Simplex::Generate( closest_corner.X(),
closest_corner.Y(),
closest_corner.Z(),
}
}```
The constant I use for scaling down the output was determined by trial-and-error because I don't math well.

3. Oh hey, regions! Can't believe I forgot to wire up that particular output. I mean, the code was right there.

4. Final verdict: pretty-looking, but slow and doesn't do anything a fully-featured Worley noise node wouldn't do. It was an interesting experiment, but I'm going to scrap this one and just move on to a good Worley implementation.

5. hey jrandom, don't understand a things but it is always nice to see ppl stretching things to get somewhere

Cheers

6. There's not a lot of activity in this forum, so I talk a lot and post code in the hopes that it might help out any random newbie node devs who stumble through here.

7. (My development cycle has slowed down greatly since I installed Skyrim on my XBox. In retrospect, that may have not been the greatest idea ever.)

8. I would love to be a node developer, but I have enough trouble just trying to use them.

9. Nodes are great and highly-intuitive. You have to completely ditch the "layer" mindset, though. Instead of layering things on top of each other, you're plugging outputs into inputs. It's wonderfully powerful.

10. Thanks jrandom, I greatly appreciate you taking the time to post your code and results.

Cheers,

-Kevin

11. If I can get Worley noise working this weekend, I'll go ahead and post the entire codebase so anyone who's trying to implement procedural texture nodes can take a look. (I won't actually be compiling the final binaries for win/mac as I don't want it to bo an official release until I get a wider variety of texture nodes implemented, so it'll be a source-only sorta deal.)

And to think this all started because I wanted a better Brick node...

12. As promised, C++11 source code for Simplex and Worley Cellular noise types. The actual noise algorithms are in Noise/ and the nodes themselves are in RainyBrain_Nodes/Textures_3D.

The code could certainly stand for some refactoring and the Worley node doesn't have bump map generation implemented yet, but the basics are all there.

13. Originally Posted by jrandom
...And to think this all started because I wanted a better Brick node...
With different bonding patterns?

14. Originally Posted by pinkmouse
With different bonding patterns?
Any good examples you could point me at? I'm not entirely sure what that means.

15. Here you go, Bonds. The standard running bond that LW and others produce is common on modern buildings that use brickwork as a decorative skin over blocks or concrete slab, but anything older than 50 years or so will use one of the alternating bonds as they are structural. I wouldn't fret about all of them, but English, Flemish, and possibly garden wall or American should do 99% of applications.

Oh, and if you haven't seen the DP Renderman brickwork node, have a look at it, it does some interesting things.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•