Page 1 of 2 12 LastLast
Results 1 to 15 of 16

Thread: I actually managed to figure out cellular noise

  1. #1
    eye kan kode gud jrandom's Avatar
    Join Date
    Dec 2009
    Location
    Seattle, WA
    Posts
    1,143

    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.

    Click image for larger version. 

Name:	Simplex_Cellular.jpg 
Views:	746 
Size:	277.6 KB 
ID:	114413

    Click image for larger version. 

Name:	Simplex_Cellular_Node.png 
Views:	377 
Size:	24.8 KB 
ID:	114414

  2. #2
    eye kan kode gud jrandom's Avatar
    Join Date
    Dec 2009
    Location
    Seattle, WA
    Posts
    1,143
    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
    //
    //  Author: Bradley Wilson
    //  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(),
                                                              Gradient_Flags_t::No_Gradients ).Noise_01() );
        }
    }
    The constant I use for scaling down the output was determined by trial-and-error because I don't math well.

  3. #3
    eye kan kode gud jrandom's Avatar
    Join Date
    Dec 2009
    Location
    Seattle, WA
    Posts
    1,143
    Oh hey, regions! Can't believe I forgot to wire up that particular output. I mean, the code was right there.

    Click image for larger version. 

Name:	Cellular_Regions.jpg 
Views:	442 
Size:	369.8 KB 
ID:	114429

    Click image for larger version. 

Name:	Cellular_Regions_Nodes.png 
Views:	352 
Size:	110.1 KB 
ID:	114430

  4. #4
    eye kan kode gud jrandom's Avatar
    Join Date
    Dec 2009
    Location
    Seattle, WA
    Posts
    1,143
    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. #5
    hey jrandom, don't understand a things but it is always nice to see ppl stretching things to get somewhere

    Cheers

  6. #6
    eye kan kode gud jrandom's Avatar
    Join Date
    Dec 2009
    Location
    Seattle, WA
    Posts
    1,143
    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. #7
    eye kan kode gud jrandom's Avatar
    Join Date
    Dec 2009
    Location
    Seattle, WA
    Posts
    1,143
    (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. #8
    Registered User GoatDude's Avatar
    Join Date
    Aug 2012
    Location
    Atlanta, GA
    Posts
    92
    I would love to be a node developer, but I have enough trouble just trying to use them.

  9. #9
    eye kan kode gud jrandom's Avatar
    Join Date
    Dec 2009
    Location
    Seattle, WA
    Posts
    1,143
    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. #10
    Thanks jrandom, I greatly appreciate you taking the time to post your code and results.

    Cheers,

    -Kevin

  11. #11
    eye kan kode gud jrandom's Avatar
    Join Date
    Dec 2009
    Location
    Seattle, WA
    Posts
    1,143
    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. #12
    eye kan kode gud jrandom's Avatar
    Join Date
    Dec 2009
    Location
    Seattle, WA
    Posts
    1,143
    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.

    Click image for larger version. 

Name:	Worley_Example_01.png 
Views:	303 
Size:	63.2 KB 
ID:	114529 Click image for larger version. 

Name:	Worley_Example_02.png 
Views:	320 
Size:	64.8 KB 
ID:	114528
    Attached Files Attached Files
    Last edited by jrandom; 05-26-2013 at 03:08 PM.

  13. #13
    Vacant, pretty vacant pinkmouse's Avatar
    Join Date
    Aug 2003
    Location
    South Yorkshire
    Posts
    1,702
    Quote Originally Posted by jrandom View Post
    ...And to think this all started because I wanted a better Brick node...
    With different bonding patterns?

  14. #14
    eye kan kode gud jrandom's Avatar
    Join Date
    Dec 2009
    Location
    Seattle, WA
    Posts
    1,143
    Quote Originally Posted by pinkmouse View Post
    With different bonding patterns?
    Any good examples you could point me at? I'm not entirely sure what that means.

  15. #15
    Vacant, pretty vacant pinkmouse's Avatar
    Join Date
    Aug 2003
    Location
    South Yorkshire
    Posts
    1,702
    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.

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

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