/*
* Copyright (c) 2016
* Side Effects Software Inc. All rights reserved.
*
* Redistribution and use of Houdini Development Kit samples in source and
* binary forms, with or without modification, are permitted provided that the
* following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. The name of Side Effects Software may not be used to endorse or
* promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*----------------------------------------------------------------------------
*/
/// Alligator Noise is provided by Side Effects Software Inc. and is licensed
/// under a Creative Commons Attribution-ShareAlike 4.0 International License.
///
/// Author: "Side Effects Software Inc"
/// Source: "http://www.sidefx.com/docs/hdk15.0/alligator_2alligator_8_c-example.html"
/// License: "http://creativecommons.org/licenses/by-sa/4.0/"
///
/// Translated and modified by Ivan Mavrov, Chaos Group Ltd. 2016
/// Contact: ivan.mavrov@chaosgroup.com
/// 3D Alligator noise implementation.
/// Returned values are in the [0, 1] range.
float alligatorNoise3D(point position) {
vector cellOffsets[27] = {
vector( 0, 0, 0),
vector( 1, 0, 0),
vector( 1, 1, 0),
vector( 0, 1, 0),
vector(-1, 1, 0),
vector(-1, 0, 0),
vector(-1, -1, 0),
vector( 0, -1, 0),
vector( 1, -1, 0),
vector( 0, 0, -1),
vector( 1, 0, -1),
vector( 1, 1, -1),
vector( 0, 1, -1),
vector(-1, 1, -1),
vector(-1, 0, -1),
vector(-1, -1, -1),
vector( 0, -1, -1),
vector( 1, -1, -1),
vector( 0, 0, 1),
vector( 1, 0, 1),
vector( 1, 1, 1),
vector( 0, 1, 1),
vector(-1, 1, 1),
vector(-1, 0, 1),
vector(-1, -1, 1),
vector( 0, -1, 1),
vector( 1, -1, 1)
};
point iPosition = floor(position);
float firstReverseSmoothPointDistance = 0.0;
float secondReverseSmoothPointDistance = 0.0;
for (int cellIndex = 0; cellIndex < 27; ++cellIndex) {
point cellOrigin = iPosition + cellOffsets[cellIndex];
vector cellPointOffset = cellnoise(cellOrigin, 0.0);
point cellPointPosition = cellOrigin + cellPointOffset;
float cellPointDistance = distance(position, cellPointPosition);
if (cellPointDistance < 1.0) {
float reverseSmoothDistance = smoothstep(0.0, 1.0, 1.0 - cellPointDistance);
float distanceMultiplier = float(cellnoise(cellOrigin, 1.0));
reverseSmoothDistance *= distanceMultiplier;
if (firstReverseSmoothPointDistance < reverseSmoothDistance) {
secondReverseSmoothPointDistance = firstReverseSmoothPointDistance;
firstReverseSmoothPointDistance = reverseSmoothDistance;
} else {
if (secondReverseSmoothPointDistance < reverseSmoothDistance) {
secondReverseSmoothPointDistance = reverseSmoothDistance;
}
}
}
}
return firstReverseSmoothPointDistance - secondReverseSmoothPointDistance;
}
/// 3D Fractal Alligator noise implementation.
/// Returned values are in the [-1, 1] range.
float fractalAlligatorNoise3D(
point position,
float lacunarity, // Houdini 2.0
float gain, // Houdini rough
int octaveCount // Houdini turbulence - 1
) {
float noiseValue = 0.0;
float amplitude = 1.0;
for (int octave = 0; octave < octaveCount; ++octave) {
noiseValue += amplitude * (alligatorNoise3D(position) - 0.5);
position *= lacunarity;
amplitude *= gain;
}
return noiseValue;
}
shader FractalAlligatorNoise
[[ string description = "Fractal Alligator noise" ]]
(
float start_frequency = 1.0
[[ string description = "Initial sampling position multiplier that affects the overall granularity." ]],
vector start_offset = vector(0.0)
[[ string description = "Offsets the initial sampling position effectively shifting the pattern in the specified direction." ]],
float lacunarity = 2.0
[[ string description = "Position (frequency) multiplier per iteration." ]],
float gain = 0.5
[[ string description = "Amplitude multiplier per iteration." ]],
int octaves = 8
[[ string description = "Number of fractal iterations." ]],
float attenuation = 1.0
[[ string description = "The power of the falloff applied to the final result." ]],
output color result = 0.0
) {
point objectPosition = transform("object", P);
point startPosition = start_frequency * objectPosition - start_offset;
float noiseValue = fractalAlligatorNoise3D(startPosition, lacunarity, gain, octaves);
noiseValue = 0.5 * noiseValue + 0.5;
noiseValue = pow(noiseValue, attenuation);
result = color(noiseValue);
}
Section
Column
width
100%
Simplex noise
...
Section
Column
width
100%
Shader code
Here is the shader code:
Code Block
language
cpp
title
simplexnoise.osl
linenumbers
true
/// 3D Simplex noise implementation.
/// Returned values are in the [0, 1] range.
float simplexNoise3D(point position) {
int perm[512] = {
151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
};
vector gradient[16] = {
vector( 1.0, 1.0, 0.0),
vector(-1.0, 1.0, 0.0),
vector( 1.0, -1.0, 0.0),
vector(-1.0, -1.0, 0.0),
vector( 1.0, 0.0, 1.0),
vector(-1.0, 0.0, 1.0),
vector( 1.0, 0.0, -1.0),
vector(-1.0, 0.0, -1.0),
vector( 0.0, 1.0, 1.0),
vector( 0.0, -1.0, 1.0),
vector( 0.0, 1.0, -1.0),
vector( 0.0, -1.0, -1.0),
vector( 1.0, 1.0, 0.0),
vector( 0.0, -1.0, 1.0),
vector(-1.0, 1.0, 0.0),
vector( 0.0, -1.0, -1.0)
};
float evaluatePointContribution(int i, int j, int k, vector offset) {
float t = 0.6 - dot(offset, offset);
if (t < 0.0) {
return 0.0;
}
float t2 = t * t;
float t4 = t2 * t2;
int gradientIndex = perm[i + perm[j + perm[k]]];
int safeGradientIndex = gradientIndex % 16;
return t4 * dot(gradient[safeGradientIndex], offset);
}
// Skewing factors for the 3D simplex grid.
float F3 = 0.333333333;
float G3 = 0.166666667;
float G3a = 2.0 * G3;
float G3b = 3.0 * G3 - 1.0;
// Skew the input space to determine the simplex cell we are in.
float skew = (position[0] + position[1] + position[2]) * F3;
point skewedPosition = position + skew;
point skewedCellOrigin = floor(skewedPosition);
// Unskew the cell origin
float unskew = (skewedCellOrigin[0] + skewedCellOrigin[1] + skewedCellOrigin[2]) * G3;
point cellOrigin = skewedCellOrigin - unskew;
// The offset from the cell's origin a.k.a point 0
vector offset0 = position - cellOrigin;
// The second point offset from the cell origin in skewed space.
vector skewedOffset1;
// The third point offset from the cell origin in skewed space.
vector skewedOffset2;
if (offset0[0] >= offset0[1]) {
if (offset0[1] >= offset0[2]) {
// X Y Z order
skewedOffset1 = vector(1, 0, 0);
skewedOffset2 = vector(1, 1, 0);
} else if (offset0[0] >= offset0[2]) {
// X Z Y order
skewedOffset1 = vector(1, 0, 0);
skewedOffset2 = vector(1, 0, 1);
} else {
// Z X Y order
skewedOffset1 = vector(0, 0, 1);
skewedOffset2 = vector(1, 0, 1);
}
} else {
if (offset0[1] < offset0[2]) {
// Z Y X order
skewedOffset1 = vector(0, 0, 1);
skewedOffset2 = vector(0, 1, 1);
} else if (offset0[0] < offset0[2]) {
// Y Z X order
skewedOffset1 = vector(0, 1, 0);
skewedOffset2 = vector(0, 1, 1);
} else {
// Y X Z order
skewedOffset1 = vector(0, 1, 0);
skewedOffset2 = vector(1, 1, 0);
}
}
// A step of (1, 0, 0) in skewed space means a step of (1 - G3, -G3, -G3) in regular space.
// A step of (0, 1, 0) in skewed space means a step of (-G3, 1 - G3, -G3) in regular space.
// A step of (0, 0, 1) in skewed space means a step of (-G3, -G3, 1 - G3) in regular space.
// The offset from point 1 in regular space.
vector offset1 = offset0 - skewedOffset1 + G3;
// The offset from point 2 in regular space.
vector offset2 = offset0 - skewedOffset2 + G3a;
// The offset from point 3 in regular space.
vector offset3 = offset0 + G3b;
// Wrap the integer indices at 256, to avoid indexing perm[] out of bounds.
int i = int(skewedCellOrigin[0]) & 255;
int j = int(skewedCellOrigin[1]) & 255;
int k = int(skewedCellOrigin[2]) & 255;
// Accumulate the contributions from the four points.
float noiseValue = 0.0;
noiseValue += evaluatePointContribution(i, j, k, offset0);
noiseValue += evaluatePointContribution(i + int(skewedOffset1[0]), j + int(skewedOffset1[1]), k + int(skewedOffset1[2]), offset1);
noiseValue += evaluatePointContribution(i + int(skewedOffset2[0]), j + int(skewedOffset2[1]), k + int(skewedOffset2[2]), offset2);
noiseValue += evaluatePointContribution(i + 1, j + 1, k + 1, offset3);
// Scale to the [-1,1] range.
noiseValue *= 32.0;
// Scale to the [0, 1] range.
return 0.5 * noiseValue + 0.5;
}
/// 3D Fractal Simplex noise implementation.
/// Returned values are in the [-1, 1] range.
float fractalSimplexNoise3D(
point position,
float lacunarity,
float gain,
int octaveCount
) {
float noiseValue = 0.0;
float amplitude = 1.0;
for (int octave = 0; octave < octaveCount; ++octave) {
noiseValue += amplitude * (simplexNoise3D(position) - 0.5);
position *= lacunarity;
amplitude *= gain;
}
return noiseValue;
}
shader FractalSimplexNoise
[[ string description = "Fractal Simplex noise" ]]
(
float start_frequency = 1.0
[[ string description = "Initial sampling position multiplier that affects the overall granularity." ]],
vector start_offset = vector(0.0)
[[ string description = "Offsets the initial sampling position effectively shifting the pattern in the specified direction." ]],
float lacunarity = 2.0
[[ string description = "Position (frequency) multiplier per iteration." ]],
float gain = 0.5
[[ string description = "Amplitude multiplier per iteration." ]],
int octaves = 8
[[ string description = "Number of fractal iterations." ]],
float attenuation = 1.0
[[ string description = "The power of the falloff applied to the final result." ]],
output color result = 0.0
) {
point objectPosition = transform("object", P);
point startPosition = start_frequency * objectPosition - start_offset;
float noiseValue = fractalSimplexNoise3D(startPosition, lacunarity, gain, octaves);
noiseValue = 0.5 * noiseValue + 0.5;
noiseValue = pow(noiseValue, attenuation);
result = color(noiseValue);
}
...
Section
Column
width
100%
Perlin flow noise
...
Section
Column
width
100%
Shader code
Here is the shader code:
Code Block
language
cpp
title
perlinflownoise.osl
linenumbers
true
int fastFloor(float x) {
return (x < 0) ? int(x) - 1 : int(x);
}
float fade(float t) {
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
}
float lerp(float t, float a, float b) {
return a + t * (b - a);
}
/// 3D Perlin flow noise implementation.
/// Returned values are in the [0, 1] range.
float perlinFlowNoise3D(point position, float flow) {
int perm[512] = {
151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
};
// Gradient component that leads to a vector of length sqrt(2).
// float a = sqrt(2)/sqrt(3);
float a = 0.81649658;
vector gradientUBase[16] = {
vector( 1.0, 0.0, 1.0), vector( 0.0, 1.0, 1.0),
vector(-1.0, 0.0, 1.0), vector( 0.0, -1.0, 1.0),
vector( 1.0, 0.0, -1.0), vector( 0.0, 1.0, -1.0),
vector(-1.0, 0.0, -1.0), vector( 0.0, -1.0, -1.0),
vector( a, a, a), vector(-a, a, -a),
vector(-a, -a, a), vector( a, -a, -a),
vector(-a, a, a), vector( a, -a, a),
vector( a, -a, -a), vector(-a, a, -a)
};
vector gradientVBase[16] = {
vector(-a, a, a), vector(-a, -a, a),
vector( a, -a, a), vector( a, a, a),
vector(-a, -a, -a), vector( a, -a, -a),
vector( a, a, -a), vector(-a, a, -a),
vector( 1.0, -1.0, 0.0), vector( 1.0, 1.0, 0.0),
vector(-1.0, 1.0, 0.0), vector(-1.0, -1.0, 0.0),
vector( 1.0, 0.0, 1.0), vector(-1.0, 0.0, 1.0),
vector( 0.0, 1.0, -1.0), vector( 0.0, -1.0, -1.0)
};
// Helper function to compute the rotated gradient.
vector getGradient(int index, float sinTheta, float cosTheta) {
int safeIndex = index % 16;
vector gradientU = gradientUBase[safeIndex];
vector gradientV = gradientVBase[safeIndex];
return cosTheta * gradientU + sinTheta * gradientV;
}
float gradientDot(int index, float sinTheta, float cosTheta, float x, float y, float z) {
vector gradient = getGradient(index, sinTheta, cosTheta);
vector value = vector(x, y, z);
return dot(gradient, value);
}
float x = position[0];
float y = position[1];
float z = position[2];
int ix = fastFloor(x);
int iy = fastFloor(y);
int iz = fastFloor(z);
float fx = x - float(ix);
float fy = y - float(iy);
float fz = z - float(iz);
ix = ix & 255;
iy = iy & 255;
iz = iz & 255;
float i = fade(fx);
float j = fade(fy);
float k = fade(fz);
int A = perm[ix ] + iy, AA = perm[A] + iz, AB = perm[A + 1] + iz;
int B = perm[ix + 1] + iy, BA = perm[B] + iz, BB = perm[B + 1] + iz;
// Sine and cosine for the gradient rotation angle
float sinTheta = 0.0;
float cosTheta = 0.0;
sincos(M_2PI * flow, sinTheta, cosTheta);
float noiseValue =
lerp(k, lerp(j, lerp(i, gradientDot(perm[AA ], sinTheta, cosTheta, fx , fy , fz ),
gradientDot(perm[BA ], sinTheta, cosTheta, fx - 1.0, fy , fz )),
lerp(i, gradientDot(perm[AB ], sinTheta, cosTheta, fx , fy - 1.0, fz ),
gradientDot(perm[BB ], sinTheta, cosTheta, fx - 1.0, fy - 1.0, fz ))),
lerp(j, lerp(i, gradientDot(perm[AA + 1], sinTheta, cosTheta, fx , fy , fz - 1.0),
gradientDot(perm[BA + 1], sinTheta, cosTheta, fx - 1.0, fy , fz - 1.0)),
lerp(i, gradientDot(perm[AB + 1], sinTheta, cosTheta, fx , fy - 1.0, fz - 1.0),
gradientDot(perm[BB + 1], sinTheta, cosTheta, fx - 1.0, fy - 1.0, fz - 1.0))));
// Scale to the [0, 1] range.
return 0.5 * noiseValue + 0.5;
}
vector perlinFlowNoise3DGradient(vector position, float flow, float delta) {
vector result = vector(
perlinFlowNoise3D(position + vector(delta, 0.0, 0.0), flow) -
perlinFlowNoise3D(position - vector(delta, 0.0, 0.0), flow),
perlinFlowNoise3D(position + vector(0.0, delta, 0.0), flow) -
perlinFlowNoise3D(position - vector(0.0, delta, 0.0), flow),
perlinFlowNoise3D(position + vector(0.0, 0.0, delta), flow) -
perlinFlowNoise3D(position - vector(0.0, 0.0, delta), flow)
);
result /= (2.0 * delta);
return result;
}
/// 3D Fractal Perlin flow noise implementation.
/// Returned values are in the [-1, 1] range.
float fractalPerlinFlowNoise3D(
point position,
float flow,
float lacunarity,
float flowRate,
float gain,
float advect,
int octaveCount
) {
float noiseValue = 0.0;
float flowValue = flow;
float amplitude = 1.0;
float advectionAmount = advect;
for (int octave = 0; octave < octaveCount; ++octave) {
float noiseOctave = amplitude * (perlinFlowNoise3D(position, flowValue) - 0.5);
noiseValue += noiseOctave;
if (advectionAmount != 0.0) {
position -= advectionAmount * noiseOctave * perlinFlowNoise3DGradient(position, flow, 0.01);
}
position *= lacunarity;
flowValue *= flowRate;
amplitude *= gain;
advectionAmount *= advect;
}
return noiseValue;
}
shader FractalPerlinFlowNoise
[[ string description = "Fractal Perlin flow noise" ]]
(
float start_frequency = 1.0
[[ string description = "Initial sampling position multiplier that affects the overall granularity." ]],
vector start_offset = vector(0.0)
[[ string description = "Offsets the initial sampling position effectively shifting the pattern in the specified direction." ]],
float flow = 1.0
[[ string description = "The coordinate of a special noise dimension with a period of 1 that naturally evolves the noise to animate it instead of sliding a 3D slice throught the noise space." ]],
float lacunarity = 2.0
[[ string description = "Position (frequency) multiplier per iteration." ]],
float flow_rate = 1.0
[[ string description = "Flow coordinate multiplier per iteration." ]],
float gain = 0.5
[[ string description = "Amplitude multiplier per iteration." ]],
float advect = 0.5
[[ string description = "Both initial advection amount and advection multiplier per iteration." ]],
int octaves = 8
[[ string description = "Number of fractal iterations." ]],
float attenuation = 1.0
[[ string description = "The power of the falloff applied to the final result." ]],
output color result = 0.0
) {
point objectPosition = transform("object", P);
point startPosition = start_frequency * objectPosition - start_offset;
float noiseValue = fractalPerlinFlowNoise3D(startPosition, flow, lacunarity, flow_rate, gain, advect, octaves);
noiseValue = 0.5 * noiseValue + 0.5;
noiseValue = pow(noiseValue, attenuation);
result = color(noiseValue);
}