Main Docs Examples Download Gallery

Implicit Modules

Implicit modules output double-precision float values. Implicit functions are derived from CImplicitModuleBase:

	class CImplicitModuleBase
	{
		public:
		virtual void setSeed(unsigned int seed);

		virtual double get(double x, double y)=0;
		virtual double get(double x, double y, double z)=0;
		virtual double get(double x, double y, double z, double w)=0;
		virtual double get(double x, double y, double z, double w, double u, double v)=0;
	};
					

Noise values are obtained by calling one of the get() methods provided, with the appropriate number of coordinates. Note that the performance of the system as a hold is affected by the dimensionality of the function called, so a 6D function will take significantly longer than a 2D function. Typical applications will probably stick with 2D or 3D versions; the higher orders are provided for the purpose of seamless mapping.

Scalar parameters

Many functions have "parameters" that affect their functionality, aside from any "source" function they might have. An example is the CImplicitSelect function. This function has a control source, a low source, a high source, a threshold parameter, and a falloff parameter. The threshold parameter is used to select between the output of lowSource and highSource, depending on if the value of controlSource is above or below threshold. All five of these inputs are instances of what ANL calls a "scalar parameter". A scalar parameter can be set to either a constant (double-precision) value, or to another function. Most will default to some sane double-precision value (ie, 0), but if desired they can be overridden with any constant or any implicit functional output. In this way, complex behaviors can be obtained through a relatively simple interface.

Module Listing

CImplicitAutoCorrect

	class CImplicitAutoCorrect : public CImplicitModuleBase
	{
		public:
		CImplicitAutoCorrect();
		CImplicitAutoCorrect(double low, double high);
		~CImplicitAutoCorrect(){}
		void setSource(CImplicitModuleBase *m);
		void setRange(double low, double high);
		void calculate();
	};
				

The AutoCorrect module is a tool to help tame the wild beasts that are fractals. When a function is set as a source to AutoCorrect, the calculate() method is called. This method will sample the input function a number of times across a region of the domain, and attempt to calculate a set of "correction parameters" to remap the function's output to a different range. Multi-fractals especially are notorious for outputting values in odd ranges, and this function provides a drop-in method for correcting them. Due to the necessity of sampling the function a number of times, there is some processing overhead when calculate() is called.

CImplicitBasisFunction

	class CImplicitBasisFunction : public CImplicitModuleBase
	{
		public:
		CImplicitBasisFunction();
		CImplicitBasisFunction(int type, int interp);

		void setType(int type);
		void setInterp(int interp);
		void setRotationAngle(double ax, double ay, double az, double angle);

		void setSeed(unsigned int seed);
	};
				

The BasisFunction function encapsulates basic noise generators. The function is customizable; you can choose what type of noise to generate and what interpolation style to use. The types of basis functions are enumerated as:

	VALUE,
	GRADIENT,
	GRADVAL,
	SIMPLEX,
	WHITE
				

The interpolation types are enumerated as:

	NONE,
	LINEAR,
	CUBIC,
	QUINTIC
				

VALUE represents value noise which is generated by assigning a pseudo-random value in the range (-1,1) to every lattice point in the integral grid, then interpolating the corner values of the conceptual "cell" in which an input coordinate location is enclosed.

VALUE noise

GRADIENT represents Perlin's original noise function. It is similar to VALUE noise in that values are assigned to each lattice point and interpolated; however; the values are calculated as the evaluation of a wavelet function centered on the lattice point. The result is smoother and with fewer grid artifacts. Gradient noise has the effect that the lattice wavelets evaluate to 0 at the lattice points, so the gradient function evaluates to 0 at all integral points in the grid, a fact that can have consequences in some applications, resulting in the appearance of grid-oriented artifacts.

GRADIENT noise

GRADVAL is a hybrid calculated as the sum of GRADIENT and VALUE noises, and is an attempt to "hide" the grid-oriented artifacts that sometimes arise from GRADIENT noise alone. While the method does fix the problem of lattice points evaluating to 0, since both GRADIENT and VALUE are tied to the grid, artifacts can still occur. See Figure 3 for an example of GRADVAL noise.

GRADVAL noise

SIMPLEX is a form of Perlin's improved noise function. Rather than interpolating the edges of a conceptual hyper-cube in N-dimensional space to obtain the noise value, simplex noise calculates a weighted sum of values assigned to the vertices of an N-dimensional "simplex". A "simplex" is the term for the simplest shape that can tile a given N-dimensional shape. For a 2D space, the simplex is an equilateral triangle. For the 3D space, it is a tetrahedron. Because a simplex has fewer vertices than the corresponding grid shape of the space, fewer calculations per sample point are required for simplex noise than for gradient or value noises. However, since simplex noise is calculated as a weighted sum of vertex contributions, rather than as an interpolation of lattice corners, simplex noise will ignore the interptype parameter passed in the constructor or via the setInterp() method. Since the size of an N-space's simplex is smaller than the corresponding unit of a grid lattice, simplex noise appears "denser" across a given region than gradient or value noise, a fact that should be taken into consideration. Simplex noise goes a long way toward reducing the appearance of grid-aligned artifacts. However, the noise is still aligned on a lattice structure, so artifacts are still there, noticeable or not. They often show up as diagonal lines slanting across the function.

SIMPLEX noise

WHITE noise is a representation of chaotic, random noise. Whereas the previous variants have all generated what is called a "continuously random" signal, WHITE noise generates a truly chaotic signal with no pattern at all.

WHITE noise

Aside from being able to assignt he type of noise generated, the user can also assign the type of interpolation used. This parameter only applies to the variants of VALUE, GRADVAL and GRADIENT. As described, SIMPLEX performs a weighted sum, and WHITE noise performs no interpolation at all. The types of interpolation are as follows:

NONE: No interpolation at all is performed.

VALUE noise, NONE interp

LINEAR: Lattice values are linearly interpolated.

VALUE noise, LINEAR interp

CUBIC:: Lattice values are performed using cubic interpolation.

VALUE noise, CUBIC interp

QUINTIC: Lattice values are interpolated using quintic interpolation. This results in the highest quality of noise.

VALUE noise, QUINTIC interp

In order to mitigate the occurrence of grid-aligned artifacts, especially in fractal functions, basis functions incorporate a 2D axial rotation (for 2D variants) and a 3D axial rotation (for 3D and above variants) that are seeded to randomized axis/angles when the function is constructed. These randomized rotations alter the alignment of the function with the lattice boundaries, and serve in most cases to help obscure the grid artifacts.

BasisFunction serves as the primary signal generator for ANL.

CImplicitBias

	class CImplicitBias : public CImplicitModuleBase
	{
		public:
		CImplicitBias(double b);
		~CImplicitBias();

		void setSource(CImplicitModuleBase *b);
		void setSource(double s);
		void setBias(double b);
		void setBias(CImplicitModuleBase *m);
	};
				

Bias has the effect of applying the following function to the output of its source:

				f(x)=pow(x, log(b)/log(0.5))
				

When applied to a function in the range of (0,1), this has the effect of "pushing" the values of the function toward 1 if b is greater than 0.5, or pushing them toward 0 if b is less than 0.5. In effect, it "biases" the function toward one end of the range or the other.

source and b are scalar parameters. They default to 0 and 0.5, respectively, and may be overridden with either another constant or with a function source.

CImplicitBlend

	class CImplicitBlend : public CImplicitModuleBase
	{
		public:
		CImplicitBlend();
		~CImplicitBlend();

		void setLowSource(CImplicitModuleBase *b);
		void setHighSource(CImplicitModuleBase *b);
		void setControlSource(CImplicitModuleBase *b);
		void setLowSource(double v);
		void setHighSource(double v);
		void setControlSource(double v);
	};
				

Blend has the effect of blending the value from lowSource with the value of highSource by linearly interpolating from one to the other using the value of controlSource. For best results, controlSource should output in the range of (0,1). All three inputs are scalar parameters that may accept either a constant value or a functional input as a source.

CImplicitBrightContrast

	class CImplicitBrightContrast : public CImplicitModuleBase
	{
		public:
		CImplicitBrightContrast();
		~CImplicitBrightContrast();
		void setSource(CImplicitModuleBase *m);
		void setSource(double v);
		void setBrightness(double b);
		void setContrastThreshold(double t);
		void setContrastFactor(double t);
		void setBrightness(CImplicitModuleBase *m);
		void setContrastThreshold(CImplicitModuleBase *m);
		void setContrastFactor(CImplicitModuleBase *m);
	};
				

The BrightContrast function provides a method for adjusting the brightness and contrast of the image. Contrast is adjusted relative to a specified threshold. Values greater than the threshold are adjust upward (brighter), while values below the threshold are adjusted downward (darker). (Note: The brightness and contrast correction provided by this function are additive, meaning that all values are brightened or darkened across the applicable range, unlike the Bias function, which lightens or darkens, but preserves the total range of the function.

CImplicitCache

	class CImplicitCache : public CImplicitModuleBase
	{
		public:
		CImplicitCache();
		~CImplicitCache();
		void setSource(CImplicitModuleBase *m);
	};
				

CCellularGenerator

	class CCellularGenerator
	{	
		public:
		CCellularGenerator();
		~CCellularGenerator();
		void setSeed(unsigned int seed);
	};
				

A CellularGenerator acts as the signal source for Cellular function. One generator can be shared between several Cellular functions, and the generator will cache results so that subsequent calls with the same coordinate location will return the cached result, rather than going through the (quite expensive) calculate process each time.

CImplicitCellular

	class CImplicitCellular : public CImplicitModuleBase
	{
		public:
		CImplicitCellular();
		CImplicitCellular(double a, double b, double c, double d);
		~CImplicitCellular(){}

		void setCoefficients(double a, double b, double c, double d);
		void setCellularSource(CCellularGenerator *m);
	};
				

The Cellular function provides an interface to a CellularGenerator to generate cellular noise based on the function originally written by Steve Worley. The function calculates F1,F2,F3 and F4 as distances to the first, second, third and fourth nearest seed points, applies the specified coefficients to the distances and sums them together, returning the result.

CImplicitClamp

	class CImplicitClamp : public CImplicitModuleBase
	{
		public:
		CImplicitClamp(double low, double high);
		~CImplicitClamp();
		void setRange(double low, double high);
		void setSource(CImplicitModuleBase *b);
	};
				

Clamp is useful for ensuring that the output of a function does not go beyond a specified range. And values beyond the given range will be clipped.

CImplicitCombiner

	class CImplicitCombiner : public CImplicitModuleBase
	{
		public:
		CImplicitCombiner(unsigned int type);
		void setType(unsigned int type);
		void clearAllSources();
		void setSource(int which, CImplicitModuleBase *b);
	};
				

Combiner is useful for mathematically combining several functions together using arithmetic operators. The function will accept up to 20 sources, and generates a combination of the sources depending on the type parameter, which can be one of ADD, MULTIPLY, MAX, MIN or AVG.

CImplicitConstant

	class CImplicitConstant : public CImplicitModuleBase
	{
		public:
		CImplicitConstant(double c);
		~CImplicitConstant();

		void setConstant(double c);
	};
				

Constant is simply that: a constant value. Note: This may be going away, as the increasing use of ScalarParameters (parameters that can either be a constant or a noise source) is making it irrelevant. Even in the case of something like a combiner, which still takes pointers to modules rather than a scalar parameter, it is just as easy to use a Cache with a constant source.

CImplicitCos

	class CImplicitCos : public CImplicitModuleBase
	{
		public:
		CImplicitCos();
		~CImplicitCos();

		void setSource(double v);
		void setSource(CImplicitModuleBase *m);
	};
				

Takes the cos() of the input function.

CImplicitExtractRGBAChannel

	class CImplicitExtractRGBAChannel : public CImplicitModuleBase
	{
		public:
		CImplicitExtractRGBAChannel();
		CImplicitExtractRGBAChannel(int channel);

		void setSource(CRGBAModuleBase *m);
		void setSource(float r, float g, float b, float a);
		void setChannel(int channel);
	};
				

ExtractRGBAChannel accepts an RGBA parameter (an RGBA constant or an RGBA module source) and extracts one of the channels. The accepted values for channel are: RED, GREEN, BLUE or ALPHA.

CImplicitFractal

	class CImplicitFractal : public CImplicitModuleBase
	{
		public:
		CImplicitFractal(unsigned int type, unsigned int basistype, unsigned int interptype);
		~CImplicitFractal();

		void setNumOctaves(int n);
		void setFrequency(double f);
		void setLacunarity(double l);
		void setGain(double g);
		void setOffset(double o);
		void setH(double h);
		void setType(unsigned int t);
		void setAllSourceTypes(unsigned int basis_type, unsigned int interp);
		void setSourceType(int which, unsigned int type, unsigned int interp);
		void overrideSource(int which, CImplicitModuleBase *b);
		void resetSource(int which);
		void resetAllSources();	
		void setSeed(unsigned int seed);
		CImplicitBasisFunction *getBasis(int which);
	};
				

Fractals are a special type of combiner that combine up to 20 noise sources using fractal methods pioneered by Perlin, Musgrave, and friends. They come in various types (specifiable through setType() or in the constructor). Each fractal has up to 20 built-in BasisFunctions whose basistype and interptype can be set via the provided methods. Additionally, you can obtain a pointer to any source of the fractal via getBasis(). Any source module in the fractal may also be overridden by an external noise function via overrideSource(). The complexity of this system serves a purpose: "generic" fractals of a given type, with basis functions of all the same type, can easily be instance just by construction, yet more complex behavior can be produced by overriding layers with external sources, to build up very complex fractals, if so desired. The basic fractal types are:

FBM

RIDGEDMULTI

BILLOW

MULTI

HYBRIDMULTI

Fractals are highly parameterized. The two most useful parameters are numoctaves which determines how many layers contribute to the fractal, and frequency which specifies the density of the function. Frequency mimics combining a ScaleDomain function to the source, multiplying the input coordinates by frequency before calculating the function. Other parameters that control the fractal are offset, lacunarity, gain and H. These parameters can have subtle, drastic, or no effect on the fractal, depending on the type, and they are typically best left alone.

CImplicitGain

	class CImplicitGain : public CImplicitModuleBase
	{
		public:
		CImplicitGain(double b);
		~CImplicitGain();

		void setSource(double v);
		void setSource(CImplicitModuleBase *b);
		void setGain(double b);
		void setGain(CImplicitModuleBase *m);
	};
				

Gain is similar in effect to Bias, and in fact uses Bias in its working. It applies the following function to the source input:

	if(t<0.5)
	{
		return bias(1.0-g, 2.0*t)/2.0;
	}
	else
	{
		return 1.0 - bias(1.0-g, 2.0 - 2.0*t)/2.0;
	}
				

This function has the effect of pushing the values of the input either toward the ends and away from the middle (if bias is >0.5) or pushing values toward the middle and away from the ends (if bias is < 0.5).

CImplicitGradient

	class CImplicitGradient : public CImplicitModuleBase
	{
		public:
		CImplicitGradient();
		~CImplicitGradient();

		void setGradient(double x1, double x2, double y1, double y2, double z1=0, double z2=0,
		double w1=0, double w2=0, double u1=0, double u2=0, double v1=0, double v2=0);
	};
				

Gradient has the effect of allowing you to specify a line segment in N-dimensional space by setting endpoints. The endpoints are set via setGradient() and the segment extends from P1=(x1,y1,z1,w1,u1,v1) to P2=(x2,y2,z2,w2,u2,v2). Only the coordinates pertinent to the dimensionality of the function being called are used, however. A gradient field is aligned with this segment such that any input coordinate is projected onto the line formed by the segment, and a value is assigned based on where on the line the projected point lies. If it lies on or beyond P1, the value is assigned as 0. If it lies on or beyond P2 the value is assigned as 1. Anything in between is assigned as a linear interpolation between 0 and 1. (This behavior may be changing; I may remove the clamping aspect, and allow values to go infinitely depending on distance from the "origin" point. Some useful things could be done in this fashion.) The result is a smooth gradient field oriented along an axis.

CImplicitRotateDomain

	class CImplicitRotateDomain : public CImplicitModuleBase
	{
		public:
		CImplicitRotateDomain(double ax, double ay, double az, double angle_deg);
		~CImplicitRotateDomain();
		void setSource(CImplicitModuleBase *m);
		void setSource(double v);
		void setAxis(double ax, double ay, double az);
		void setAxis(CImplicitModuleBase *ax, CImplicitModuleBase *ay, CImplicitModuleBase *az);
		void setAxisX(double ax);
		void setAxisY(double ay);
		void setAxisZ(double az);
		void setAxisX(CImplicitModuleBase *ax);
		void setAxisY(CImplicitModuleBase *ay);
		void setAxisZ(CImplicitModuleBase *az);

		void setAngle(double a);
		void setAngle(CImplicitModuleBase *a);
				

RotateDomain applies a domain rotation to the input function. That is, it actually modifies the coordinates that the input function will be called by. If the RotateDomain is called by the input coordinate (x,y), it will call its source with the input coordinate (nx,ny) where (nx,ny) is a transformation of the original input; specifically, a rotation around an axis. This function has slightly different behavior depending on if the 2D version is called or if some higher version is called. 2D version rotates the input around the Z axis by the given angular amount, and the axis sources set by setAxis() are ignored. 3D and above, however, rotate the domain around the axis specified.

CImplicitScaleDomain

	class CImplicitScaleDomain : public CImplicitModuleBase
	{
		public:
		CImplicitScaleDomain();
		CImplicitScaleDomain(double x, double y, double z=1, double w=1, double u=1, double v=1);
		void setScale(double x, double y, double z=1, double w=1, double u=1, double v=1);
		void setXScale(double x);
		void setYScale(double x);
		void setZScale(double x);
		void setWScale(double x);
		void setUScale(double x);
		void setVScale(double x);
		void setXScale(CImplicitModuleBase *x);
		void setYScale(CImplicitModuleBase *y);
		void setZScale(CImplicitModuleBase *z);
		void setWScale(CImplicitModuleBase *w);
		void setUScale(CImplicitModuleBase *u);
		void setVScale(CImplicitModuleBase *v);
	
		void setSource(CImplicitModuleBase *m);
		void setSource(double v);
	};

				

ScaleDomain applies a domain scaling to the coordinates input to the function.

CImplicitScaleOffset

	class CImplicitScaleOffset : public CImplicitModuleBase
	{
		public:
		CImplicitScaleOffset(double scale, double offset);
		~CImplicitScaleOffset();
	
		void setSource(CImplicitModuleBase *b);
		void setSource(double v);
		void setScale(double scale);
		void setOffset(double offset);
		void setScale(CImplicitModuleBase *scale);
		void setOffset(CImplicitModuleBase *offset);
	};
				

ScaleOffset applies a scaling and translation factor to the output of its source function, as v*scale+offset.

CImplicitSelect

	class CImplicitSelect : public CImplicitModuleBase
	{
		public:
		CImplicitSelect();
		~CImplicitSelect();
		void setLowSource(CImplicitModuleBase *b);
		void setHighSource(CImplicitModuleBase *b);
		void setControlSource(CImplicitModuleBase *b);
		void setLowSource(double v);
		void setHighSource(double v);
		void setControlSource(double v);
		void setThreshold(double t);
		void setFalloff(double f);
		void setThreshold(CImplicitModuleBase *m);
		void setFalloff(CImplicitModuleBase *m);
	};
				

Select is used to choose between one function or another based on the output value of a third control function. Two parameters control how the select is performed, threshold and falloff. Threshold determines where the dividing line is; values on one side of threshold are taken from one source module, while values on the other side are taken from the second source. Falloff defines the width of a soft "blend" zone that straddles threshold, helping to smooth the transition between the two functions.

In the above image, a gradient function was used as the control source, with the falloff set at 0.5:

In the blend on the left you can clearly see a sharp divide between the two functions, due to no falloff. On the right, you can see how falloff smooths the sharp transition between the two.

CImplicitSin

	class CImplicitSin : public CImplicitModuleBase
	{
		public:
		CImplicitSin();
		~CImplicitSin();

		void setSource(double v);
		void setSource(CImplicitModuleBase *m);
	};
				

Takes the sin() of the input source.

CImplicitSphere

	class CImplicitSphere : public CImplicitModuleBase
	{	
		public:
		CImplicitSphere();
		~CImplicitSphere();
		void setCenter(double cx,double cy,double cz=0,double cw=0,double cu=0,double cv=0);
		void setCenterX(double cx);
		void setCenterY(double cy);
		void setCenterZ(double cz);
		void setCenterW(double cw);
		void setCenterU(double cu);
		void setCenterV(double cv);
		void setCenterX(CImplicitModuleBase *cx);
		void setCenterY(CImplicitModuleBase *cy);
		void setCenterZ(CImplicitModuleBase *cz);
		void setCenterW(CImplicitModuleBase *cw);
		void setCenterU(CImplicitModuleBase *cu);
		void setCenterV(CImplicitModuleBase *cv);

		void setRadius(double r);
		void setRadius(CImplicitModuleBase *r);
	};
				

Generates a hyper sphere as a distance field. Values between the center and the radius are interpolated between 0 and 1, while values beyond radius are 0. The individual axis components of the center point, as well as the radius, are specifiable as either constants or as noise functions, making this an extremely flexible sphere indeed. Following are images taken as cross-sections of the sphere in the 2D plane, the one on the left with all constants for the components, the one in the center with constants for center and a fractal function for radius, and the one on the right with a fractal for the x component, and a constant radius.

CImplicitTranslateDomain

	class CImplicitTranslateDomain : public CImplicitModuleBase
	{
		public:
		CImplicitTranslateDomain();
		~CImplicitTranslateDomain();

		void setXAxisSource(CImplicitModuleBase *m);
		void setYAxisSource(CImplicitModuleBase *m);
		void setZAxisSource(CImplicitModuleBase *m);
		void setWAxisSource(CImplicitModuleBase *m);
		void setUAxisSource(CImplicitModuleBase *m);
		void setVAxisSource(CImplicitModuleBase *m);

		void setXAxisSource(double v);
		void setYAxisSource(double v);
		void setZAxisSource(double v);
		void setWAxisSource(double v);
		void setUAxisSource(double v);
		void setVAxisSource(double v);

		void setSource(CImplicitModuleBase *m);
		void setSource(double v);
	};
				

TranslateDomain is used to translate the input coordinates of a function. Each axis is specifiable as a constant or noise source. This application of domain transformation is commonly called turbulence and is useful in generating many types of effects. Here is a single BasisFunction of type GRADIENT, transformed in the X axis by a fractal:

On the left is the un-transformed basis function, on the right is the result of applying turbulence on the X axis. This technique is an extremely useful tool, used in many effects.

All content on page copyright 2011 Joshua Tippetts