Beispiel #1
0
        protected virtual void UpdateNoisePropertyBlock(NoiseStruct noiseStruct)
        {
            NoisePropertyBlock.SetTexture("_Splerp", noiseStruct.splerpTexture);
            NoisePropertyBlock.SetTexture("_PerlinHash", NoiseUtils.PerlinHashTexture);
            switch (noiseStruct.renderType)
            {
            case RenderType.Render1D:
                NoisePropertyBlock.SetTexture("_Gradients", NoiseUtils.Gradients1DTexture);
                break;

            case RenderType.Render2D:
                NoisePropertyBlock.SetTexture("_Gradients", NoiseUtils.Gradients2DTexture);
                break;

            case RenderType.Render3D:
                NoisePropertyBlock.SetTexture("_Gradients", NoiseUtils.Gradients3DTexture);
                break;

            default:
                throw new ArgumentOutOfRangeException("noiseStruct", noiseStruct.renderType, "Given RenderType not supported.");
            }
            // TODO: worldTransform does not contain proper object position... why?
            NoisePropertyBlock.SetMatrix("_WorldTransform",
                                         noiseStruct.worldTransform ? noiseStruct.worldTransform.localToWorldMatrix : Matrix4x4.identity);
            NoisePropertyBlock.SetFloat("_Resolution", noiseStruct.resolution);
            NoisePropertyBlock.SetFloat("_Frequency", noiseStruct.frequency);
            NoisePropertyBlock.SetFloat("_Amplitude", noiseStruct.amplitude);
        }
        protected override float Value2D(Vector3 point, NoiseStruct noiseStruct)
        {
            point *= noiseStruct.frequency;
            //Calculate Integer Lattice Points and interpolants t
            int i0X = Mathf.FloorToInt(point.x);
            int i0Y = Mathf.FloorToInt(point.y);
            var t0  = new Vector2(point.x - i0X, point.y - i0Y);

            i0X &= HashMask;
            i0Y &= HashMask;
            int i1X = i0X + 1;
            int i1Y = i0Y + 1;

            int h0  = NoiseUtils.PerlinHash[i0X];
            int h1  = NoiseUtils.PerlinHash[i1X];
            int h00 = NoiseUtils.PerlinHash[h0 + i0Y];
            int h01 = NoiseUtils.PerlinHash[h0 + i1Y];
            int h10 = NoiseUtils.PerlinHash[h1 + i0Y];
            int h11 = NoiseUtils.PerlinHash[h1 + i1Y];

            t0.x = NoiseUtils.Splerp(ref noiseStruct.splerp, 0f, 1f, t0.x);
            t0.y = NoiseUtils.Splerp(ref noiseStruct.splerp, 0f, 1f, t0.y);
            return
                (Mathf.Lerp(Mathf.Lerp(h00, h10, t0.x),
                            Mathf.Lerp(h01, h11, t0.x), t0.y) * (1f / HashMask));
        }
        protected override float Value1D(Vector3 point, NoiseStruct noiseStruct)
        {
            point *= noiseStruct.frequency;
            //Calculate Integer Lattice Points
            int ix = Mathf.FloorToInt(point.x);

            ix &= HashMask;
            return(NoiseUtils.PerlinHash[ix] * (1f / HashMask));
        }
        protected override float Value1D(Vector3 point, NoiseStruct noiseStruct)
        {
            point *= noiseStruct.frequency;
            //Calculate Integer Lattice Points and interpolants t
            int   i0X = Mathf.FloorToInt(point.x);
            float t   = point.x - i0X;

            i0X &= HashMask;
            int i1X = i0X + 1;

            int h0 = NoiseUtils.PerlinHash[i0X];
            int h1 = NoiseUtils.PerlinHash[i1X];

            t = NoiseUtils.Splerp(ref noiseStruct.splerp, 0f, 1f, t);
            return(Mathf.Lerp(h0, h1, t) * (1f / HashMask));
        }
Beispiel #5
0
        public virtual void UpdateNoise(Renderer renderer, NoiseStruct noiseStruct)
        {
            //TODO: Seperate this and only call when needed
            switch (noiseStruct.renderType)
            {
            case RenderType.Render1D:
                renderer.sharedMaterial.EnableKeyword("RENDERTYPE_1D");
                renderer.sharedMaterial.DisableKeyword("RENDERTYPE_2D");
                renderer.sharedMaterial.DisableKeyword("RENDERTYPE_3D");
                break;

            case RenderType.Render2D:
                renderer.sharedMaterial.DisableKeyword("RENDERTYPE_1D");
                renderer.sharedMaterial.EnableKeyword("RENDERTYPE_2D");
                renderer.sharedMaterial.DisableKeyword("RENDERTYPE_3D");
                break;

            case RenderType.Render3D:
                renderer.sharedMaterial.DisableKeyword("RENDERTYPE_1D");
                renderer.sharedMaterial.DisableKeyword("RENDERTYPE_2D");
                renderer.sharedMaterial.EnableKeyword("RENDERTYPE_3D");
                break;

            default:
                throw new ArgumentOutOfRangeException("noiseStruct", noiseStruct.renderType, "Given RenderType not supported.");
            }
            if (noiseStruct.range == Range)
            {
                renderer.sharedMaterial.DisableKeyword("RANGE_ADJUST");
                renderer.sharedMaterial.EnableKeyword("RANGE_NOADJUST");
            }
            else
            {
                renderer.sharedMaterial.EnableKeyword("RANGE_ADJUST");
                renderer.sharedMaterial.DisableKeyword("RANGE_NOADJUST");
            }
            renderer.GetPropertyBlock(NoisePropertyBlock);

            UpdateNoisePropertyBlock(noiseStruct);

            renderer.SetPropertyBlock(NoisePropertyBlock);
        }
Beispiel #6
0
        public float Value(Vector3 point, NoiseStruct noiseStruct)
        {
            float value;

            switch (noiseStruct.renderType)
            {
            case RenderType.Render1D:
                value = Value1D(point, noiseStruct);
                break;

            case RenderType.Render2D:
                value = Value2D(point, noiseStruct);
                break;

            case RenderType.Render3D:
                value = Value3D(point, noiseStruct);
                break;

            default:
                throw new ArgumentOutOfRangeException("noiseStruct", noiseStruct.renderType, "Given RenderType not supported.");
            }
            if (noiseStruct.range != Range)
            {
                switch (noiseStruct.range)
                {
                case Range.OneGreaterZero:
                    //Convert to OneGreaterZero
                    value = (value / 2f) + 0.5f;
                    break;

                case Range.OneAroundZero:
                    //Convert to OneAroundZero
                    value = (value - 0.5f) * 2f;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            return(value * noiseStruct.amplitude);
        }
Beispiel #7
0
        protected override float Value2D(Vector3 point, NoiseStruct noiseStruct)
        {
            point *= noiseStruct.frequency;
            //Calculate Integer Lattice Points and interpolants t
            int i0X = Mathf.FloorToInt(point.x);
            int i0Y = Mathf.FloorToInt(point.y);

            var t0 = new Vector2(point.x - i0X, point.y - i0Y);
            var t1 = new Vector2(t0.x - 1f, t0.y - 1f);

            i0X &= NoiseUtils.HashMask;
            i0Y &= NoiseUtils.HashMask;
            int i1X = i0X + 1;
            int i1Y = i0Y + 1;

            int h0  = NoiseUtils.PerlinHash[i0X];
            int h1  = NoiseUtils.PerlinHash[i1X];
            int h00 = NoiseUtils.PerlinHash[h0 + i0Y];
            int h01 = NoiseUtils.PerlinHash[h0 + i1Y];
            int h10 = NoiseUtils.PerlinHash[h1 + i0Y];
            int h11 = NoiseUtils.PerlinHash[h1 + i1Y];

            var g00 = NoiseUtils.Gradients2D[h00 & NoiseUtils.GradientsMask2D];
            var g01 = NoiseUtils.Gradients2D[h01 & NoiseUtils.GradientsMask2D];
            var g10 = NoiseUtils.Gradients2D[h10 & NoiseUtils.GradientsMask2D];
            var g11 = NoiseUtils.Gradients2D[h11 & NoiseUtils.GradientsMask2D];

            float v00 = Vector2.Dot(g00, new Vector2(t0.x, t0.y));
            float v01 = Vector2.Dot(g01, new Vector2(t0.x, t1.y));
            float v10 = Vector2.Dot(g10, new Vector2(t1.x, t0.y));
            float v11 = Vector2.Dot(g11, new Vector2(t1.x, t1.y));

            //t0.x = NoiseUtils.Splerp(ref noiseStruct.splerp, 0f, 1f, t0.x);
            //t0.y = NoiseUtils.Splerp(ref noiseStruct.splerp, 0f, 1f, t0.y);
            t0.x = NoiseUtils.SmootherStep(t0.x);
            t0.y = NoiseUtils.SmootherStep(t0.y);
            return
                (Mathf.Lerp(Mathf.Lerp(v00, v10, t0.x),
                            Mathf.Lerp(v01, v11, t0.x), t0.y) * NoiseUtils.Sqr2);
        }
Beispiel #8
0
        protected override float Value3D(Vector3 point, NoiseStruct noiseStruct)
        {
            point *= noiseStruct.frequency;

            //Skew Point
            double skew = (point.x + point.y + point.z) * Skew3;

            //Determine surrounding unit cube with integer coorindates in skewed space
            i = (int)Math.Floor(point.x + skew);
            j = (int)Math.Floor(point.y + skew);
            k = (int)Math.Floor(point.z + skew);
            double unskew = (i + j + k) * Unskew3;

            u = point.x - i + unskew;
            v = point.y - j + unskew;
            w = point.z - k + unskew;
            A = new[] { 0, 0, 0 };
            int hi = u >= w ? u >= v ? 0 : 1 : v >= w ? 1 : 2;
            int lo = u < w ? u < v ? 0 : 1 : v < w ? 1 : 2;

            return((float)(8.0 * (K(hi) + K(3 - hi - lo) + K(lo) + K(0))));
        }
Beispiel #9
0
        protected override float Value1D(Vector3 point, NoiseStruct noiseStruct)
        {
            point *= noiseStruct.frequency;
            //Calculate Integer Lattice Points and interpolants t
            int   i0X = Mathf.FloorToInt(point.x);
            float t0  = point.x - i0X;
            float t1  = t0 - 1f;

            i0X &= NoiseUtils.HashMask;
            int i1X = i0X + 1;

            int h0 = NoiseUtils.PerlinHash[i0X];
            int h1 = NoiseUtils.PerlinHash[i1X];

            float g0 = NoiseUtils.Gradients1D[h0 & NoiseUtils.GradientsMask1D];
            float g1 = NoiseUtils.Gradients1D[h1 & NoiseUtils.GradientsMask1D];

            float v0 = g0 * t0;
            float v1 = g1 * t1;

            //t0 = NoiseUtils.Splerp(ref noiseStruct.splerp, 0f, 1f, t0);
            t0 = NoiseUtils.SmootherStep(t0);
            return(Mathf.Lerp(v0, v1, t0) * 2f);
        }
        protected override float Value3D(Vector3 point, NoiseStruct noiseStruct)
        {
            point *= noiseStruct.frequency;

            float n0, n1, n2, n3; // Noise contributions form the four corners

            // Factor to skew simplex tetrahedron grid to unit cube grid
            float skew = (point.x + point.y + point.z) * Skew3;
            // Find integer lattice points in skewed space
            int i0 = Mathf.FloorToInt(point.x + skew);
            int j0 = Mathf.FloorToInt(point.y + skew);
            int k0 = Mathf.FloorToInt(point.z + skew);
            // Factor to unskew back to simplex tetrahedron grid
            float unskew = (i0 + j0 + k0) * Unskew3;
            // Unskew integer lattice points in skewed space back into simplex grid
            // This is now the origin point of our simplex cell, called first corner
            //var corner0 = new Vector3(i0 - unskew, j0 - unskew, k0 - unskew);
            // Relative coordinates from first corner to input point within simplex cell
            var t0 = new Vector3(point.x - i0 + unskew, point.y - j0 + unskew, point.z - k0 + unskew);

            // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
            // Determine which simplex we are in.
            int i1, j1, k1;				// Offsets for second corner of simplex cell in skewed space
            int i2, j2, k2;				// Offsets for third corner of simplex cell in skewed space
            int i3 = 1, j3 = 1, k3 = 1; // Offsets for fourth corner of simplex cell in skewed space
            if (t0.x >= t0.y)
            {
                if (t0.y >= t0.z)			// x > y > z
                {
                    i1 = 1; j1 = 0; k1 = 0;
                    i2 = 1; j2 = 1; k2 = 0;
                } else if (t0.x >= t0.z)	// x > z > y
                {
                    i1 = 1; j1 = 0; k1 = 0;
                    i2 = 1; j2 = 0; k2 = 1;
                } else						// z > x > y
                {
                    i1 = 0; j1 = 0; k1 = 1;
                    i2 = 1; j2 = 0; k2 = 1;
                }
            } else // t0.x < t0.y
            {
                if (t0.y < t0.z)			// z > y > x
                {
                    i1 = 0; j1 = 0; k1 = 1;
                    i2 = 0; j2 = 1; k2 = 1;
                } else if (t0.x < t0.z)		// y > z > x
                {
                    i1 = 0; j1 = 1; k1 = 0;
                    i2 = 0; j2 = 1; k2 = 1;
                } else						// y > x > z
                {
                    i1 = 0; j1 = 1; k1 = 0;
                    i2 = 1; j2 = 1; k2 = 0;
                }
            }

            var t1 = new Vector3(t0.x - i1 + Unskew3, t0.y - j1 + Unskew3, t0.z - k1 + Unskew3);
            var t2 = new Vector3(t0.x - i2 + 2*Unskew3, t0.y - j2 + 2*Unskew3, t0.z - k2 + 2*Unskew3);
            var t3 = new Vector3(t0.x - i3 + 3*Unskew3, t0.y - j3 + 3*Unskew3, t0.z - k3 + 3*Unskew3);

            // Work out the hashed gradient indices gi of the four simplex corners
            int ii = i0 & NoiseUtils.HashMask;
            int jj = j0 & NoiseUtils.HashMask;
            int kk = k0 & NoiseUtils.HashMask;
            int gi0 = NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[kk     ] + jj     ] + ii] & NoiseUtils.GradientsMask3D; // Gradient index for first corner
            int gi1 = NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[kk + k1] + jj + j1] + ii + i1] & NoiseUtils.GradientsMask3D; // Gradient index for second corner
            int gi2 = NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[kk + k2] + jj + j2] + ii + i2] & NoiseUtils.GradientsMask3D; // Gradient index for third corner
            int gi3 = NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[kk + k3] + jj + j3] + ii + i3] & NoiseUtils.GradientsMask3D; // Gradient index for forth corner

            // Calculate the contribution c from the four corners
            float c0 = 0.6f - t0.x * t0.x - t0.y * t0.y - t0.z * t0.z;
            if (c0 < 0) n0 = 0.0f;
            else n0 = Mathf.Pow(c0, 4) * Vector3.Dot(NoiseUtils.Gradients3D[gi0], t0);

            float c1 = 0.6f - t1.x * t1.x - t1.y * t1.y - t1.z * t1.z;
            if (c1 < 0) n1 = 0.0f;
            else n1 = Mathf.Pow(c1, 4) * Vector3.Dot(NoiseUtils.Gradients3D[gi1], t1);

            float c2 = 0.6f - t2.x * t2.x - t2.y * t2.y - t2.z * t2.z;
            if (c2 < 0) n2 = 0.0f;
            else n2 = Mathf.Pow(c2, 4) * Vector3.Dot(NoiseUtils.Gradients3D[gi2], t2);

            float c3 = 0.6f - t3.x * t3.x - t3.y * t3.y - t3.z * t3.z;
            if (c3 < 0) n3 = 0.0f;
            else n3 = Mathf.Pow(c3, 4) * Vector3.Dot(NoiseUtils.Gradients3D[gi3], t3);

            // Add contributions from each corner to get the final noise value.
            // The result is scaled to return values in the interval [-1,1].
            return 8.0f * (n0 + n1 + n2 + n3);
        }
 protected override float Value3D(Vector3 point, NoiseStruct noiseStruct)
 {
     point *= noiseStruct.frequency;
     return(Mathf.Sin(point.x) * Mathf.Sin(point.y) * Mathf.Sin(point.z));
 }
Beispiel #12
0
        protected override float Value2D(Vector3 point, NoiseStruct noiseStruct)
        {
            point *= noiseStruct.frequency;

            return(0);
        }
 protected override float Value1D(Vector3 point, NoiseStruct noiseStruct)
 {
     point *= 2 * Mathf.PI * noiseStruct.frequency;
     return(Mathf.Sin(point.x));
 }
Beispiel #14
0
 protected override float Value3D(Vector3 point, NoiseStruct noiseStruct)
 {
     return((float)m_random.NextDouble());
 }
Beispiel #15
0
 protected abstract float Value3D(Vector3 point, NoiseStruct noiseStruct);
Beispiel #16
0
        protected override float Value3D(Vector3 point, NoiseStruct noiseStruct)
        {
            point *= noiseStruct.frequency;
            //Calculate Integer Lattice Points and interpolants t
            int i0X = Mathf.FloorToInt(point.x);
            int i0Y = Mathf.FloorToInt(point.y);
            int i0Z = Mathf.FloorToInt(point.z);
            //Get point relative to wavelet center
            var t0 = new Vector3(point.x - i0X, point.y - i0Y, point.z - i0Z);
            var t1 = new Vector3(t0.x - 1f, t0.y - 1f, t0.z - 1f);

            i0X &= NoiseUtils.HashMask;
            i0Y &= NoiseUtils.HashMask;
            i0Z &= NoiseUtils.HashMask;
            int i1X = i0X + 1;
            int i1Y = i0Y + 1;
            int i1Z = i0Z + 1;

            // Fold x,y,z using permuation table
            int h0   = NoiseUtils.PerlinHash[i0X];
            int h1   = NoiseUtils.PerlinHash[i1X];
            int h00  = NoiseUtils.PerlinHash[h0 + i0Y];
            int h01  = NoiseUtils.PerlinHash[h0 + i1Y];
            int h10  = NoiseUtils.PerlinHash[h1 + i0Y];
            int h11  = NoiseUtils.PerlinHash[h1 + i1Y];
            int h000 = NoiseUtils.PerlinHash[h00 + i0Z];
            int h001 = NoiseUtils.PerlinHash[h00 + i1Z];
            int h010 = NoiseUtils.PerlinHash[h01 + i0Z];
            int h011 = NoiseUtils.PerlinHash[h01 + i1Z];
            int h100 = NoiseUtils.PerlinHash[h10 + i0Z];
            int h101 = NoiseUtils.PerlinHash[h10 + i1Z];
            int h110 = NoiseUtils.PerlinHash[h11 + i0Z];
            int h111 = NoiseUtils.PerlinHash[h11 + i1Z];

            var g000 = NoiseUtils.Gradients3D[h000 & NoiseUtils.GradientsMask3D];
            var g001 = NoiseUtils.Gradients3D[h001 & NoiseUtils.GradientsMask3D];
            var g010 = NoiseUtils.Gradients3D[h010 & NoiseUtils.GradientsMask3D];
            var g011 = NoiseUtils.Gradients3D[h011 & NoiseUtils.GradientsMask3D];
            var g100 = NoiseUtils.Gradients3D[h100 & NoiseUtils.GradientsMask3D];
            var g101 = NoiseUtils.Gradients3D[h101 & NoiseUtils.GradientsMask3D];
            var g110 = NoiseUtils.Gradients3D[h110 & NoiseUtils.GradientsMask3D];
            var g111 = NoiseUtils.Gradients3D[h111 & NoiseUtils.GradientsMask3D];

            float v000 = Vector3.Dot(g000, new Vector3(t0.x, t0.y, t0.z));
            float v001 = Vector3.Dot(g001, new Vector3(t0.x, t0.y, t1.z));
            float v010 = Vector3.Dot(g010, new Vector3(t0.x, t1.y, t0.z));
            float v011 = Vector3.Dot(g011, new Vector3(t0.x, t1.y, t1.z));
            float v100 = Vector3.Dot(g100, new Vector3(t1.x, t0.y, t0.z));
            float v101 = Vector3.Dot(g101, new Vector3(t1.x, t0.y, t1.z));
            float v110 = Vector3.Dot(g110, new Vector3(t1.x, t1.y, t0.z));
            float v111 = Vector3.Dot(g111, new Vector3(t1.x, t1.y, t1.z));

            //t0.x = NoiseUtils.Splerp(ref noiseStruct.splerp, 0f, 1f, t0.x);
            //t0.y = NoiseUtils.Splerp(ref noiseStruct.splerp, 0f, 1f, t0.y);
            //t0.z = NoiseUtils.Splerp(ref noiseStruct.splerp, 0f, 1f, t0.z);

            //Compute the dropoff
            t0.x = NoiseUtils.SmootherStep(t0.x);
            t0.y = NoiseUtils.SmootherStep(t0.y);
            t0.z = NoiseUtils.SmootherStep(t0.z);
            return(Mathf.Lerp(
                       Mathf.Lerp(Mathf.Lerp(v000, v100, t0.x),
                                  Mathf.Lerp(v010, v110, t0.x), t0.y),
                       Mathf.Lerp(Mathf.Lerp(v001, v101, t0.x),
                                  Mathf.Lerp(v011, v111, t0.x), t0.y),
                       t0.z));
        }
        protected override float Value2D(Vector3 point, NoiseStruct noiseStruct)
        {
            point *= noiseStruct.frequency;

            float n0, n1, n2; // Noise contributions form the three corners

            // Skew simplex triangle grid to rightangle isosceles triangles, two of which form a square
            float skew = (point.x + point.y) * Skew2;
            // Find integer lattice points in skewed space
            int i0 = Mathf.FloorToInt(point.x + skew);
            int j0 = Mathf.FloorToInt(point.y + skew);

            float unskew = (i0 + j0) * Unskew2;
            // Unskew integer lattice points in skewed space back into simplex grid
            // This is now the origin point of our simplex cell, called first corner
            //var corner0 = new Vector2(i0 - unskew, j0 - unskew);
            // Relative coordinates from first corner to input point within simplex cell
            var t0 = new Vector2(point.x - i0 + unskew, point.y - j0 + unskew);

            // For the 2D case, the simplex shape is a triangle.
            // Determine which simplex we are in.
            int i1, j1;         // Offsets for second corner of simplex cell in skewed space
            int i2 = 1, j2 = 1; // Offsets for third corner of simplex cell in skewed space

            if (t0.x > t0.y)	//lower triangle
            {
                i1 = 1;
                j1 = 0;
            }
            else				// upper triangle
            {
                i1 = 0;
                j1 = 1;
            }

            var t1 = new Vector2(t0.x - i1 + Unskew2, t0.y - j1 + Unskew2);
            var t2 = new Vector2(t0.x - i2 + 2 * Unskew2, t0.y - j2 + 2 * Unskew2);

            // Work out the hashed gradient indices gi of the four simplex corners
            int ii = i0 & NoiseUtils.HashMask;
            int jj = j0 & NoiseUtils.HashMask;
            int gi0 = NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[jj     ] + ii] & NoiseUtils.GradientsMask3D; // Gradient index for first corner
            int gi1 = NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[jj + j1] + ii + i1] & NoiseUtils.GradientsMask3D; // Gradient index for second corner
            int gi2 = NoiseUtils.PerlinHash[NoiseUtils.PerlinHash[jj + j2] + ii + i2] & NoiseUtils.GradientsMask3D; // Gradient index for third corner

            // Calculate the contribution c from the four corners
            float c0 = 0.5f - (t0.x * t0.x + t0.y * t0.y);
            if (c0 < 0) n0 = 0.0f;
            else n0 = Mathf.Pow(c0, 4) * dot(NoiseUtils.Gradients3D[gi0], t0);

            float c1 = 0.5f - t1.x * t1.x - t1.y * t1.y;
            if (c1 < 0) n1 = 0.0f;
            else n1 = Mathf.Pow(c1, 4) * dot(NoiseUtils.Gradients3D[gi1], t1);

            float c2 = 0.5f - t2.x * t2.x - t2.y * t2.y;
            if (c2 < 0) n2 = 0.0f;
            else n2 = Mathf.Pow(c2, 4) * dot(NoiseUtils.Gradients3D[gi2], t2);

            // Add contributions from each corner to get the final noise value.
            // The result is scaled to return values in the interval [-1,1].
            return 70f * (n0 + n1 + n2);
        }