# I actually managed to figure out cellular noise

#### jrandom

##### eye kan kode gud
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.

#### jrandom

##### eye kan kode gud
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.

#### jrandom

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

#### jrandom

##### eye kan kode gud
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.

#### probiner

##### F&#559;rum Mole
hey jrandom, don't understand a things but it is always nice to see ppl stretching things to get somewhere

Cheers

#### jrandom

##### eye kan kode gud
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.

#### jrandom

##### eye kan kode gud
(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.)

#### GoatDude

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

#### jrandom

##### eye kan kode gud
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.

#### kmacphail

##### No Pants!
Thanks jrandom, I greatly appreciate you taking the time to post your code and results.

Cheers,

-Kevin

#### jrandom

##### eye kan kode gud
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...

#### jrandom

##### eye kan kode gud
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.

#### Attachments

• Demo Proc 3D Nodes.zip
103.1 KB · Views: 381
Last edited:

#### pinkmouse

##### Vacant, pretty vacant
...And to think this all started because I wanted a better Brick node...

With different bonding patterns?

#### jrandom

##### eye kan kode gud
With different bonding patterns?

Any good examples you could point me at? I'm not entirely sure what that means.

#### pinkmouse

##### Vacant, pretty vacant
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.

#### Trinnian_2

##### New member
I just made a plugin for 4D Simplex Noise, but not node-based. Then i saw this thread. Arrrggghhhh.