void Update()
    {
        float[] offset = new float[] { 0.5f * Time.time, 0.25f * Time.time, 0.1f * Time.time };
        int     seed   = (int)Mathf.Floor(2.0f * Time.time);

        float[] output1    = new float[m_gridExtent];
        float[] output1Sqr = new float[m_gridExtent * m_gridExtent];
        float[] output1Cub = new float[m_gridExtent * m_gridExtent * m_gridExtent];
        float[,] output2  = new float[m_gridExtent, m_gridExtent];
        float[,,] output3 = new float[m_gridExtent, m_gridExtent, m_gridExtent];
        Vector2[] output1v2    = new Vector2[m_gridExtent];
        Vector2[] output1v2Sqr = new Vector2[m_gridExtent * m_gridExtent];
        Vector2[,] output2v2 = new Vector2[m_gridExtent, m_gridExtent];
        Vector3[] output1v3    = new Vector3[m_gridExtent];
        Vector3[] output1v3Sqr = new Vector3[m_gridExtent * m_gridExtent];
        Vector3[] output1v3Cub = new Vector3[m_gridExtent * m_gridExtent * m_gridExtent];
        Vector3[,] output2v3  = new Vector3[m_gridExtent, m_gridExtent];
        Vector3[,,] output3v3 = new Vector3[m_gridExtent, m_gridExtent, m_gridExtent];
        float[] scale  = new float[] { 3.0f, 3.0f, 3.0f };
        float[] period = new float[] { 0.15f, 0.15f, 0.15f };

        Vector2[] input1v2    = new Vector2[m_gridExtent];
        Vector2[] input1v2Sqr = new Vector2[m_gridExtent * m_gridExtent];
        Vector3[] input1v3    = new Vector3[m_gridExtent];
        Vector3[] input1v3Sqr = new Vector3[m_gridExtent * m_gridExtent];
        Vector3[] input1v3Cub = new Vector3[m_gridExtent * m_gridExtent * m_gridExtent];
        for (int z = 0; z < m_gridExtent; ++z)
        {
            for (int y = 0; y < m_gridExtent; ++y)
            {
                for (int x = 0; x < m_gridExtent; ++x)
                {
                    int i = ((z * m_gridExtent) + y) * m_gridExtent + x;
                    if (z == 0)
                    {
                        if (y == 0)
                        {
                            Vector3 p1 = new Vector3(x, y, z);
                            input1v2[i].Set(p1.x, p1.y);
                            input1v3[i] = p1;
                        }

                        Vector3 p2 = new Vector3(x, y, z);
                        input1v2Sqr[i].Set(p2.x, p2.y);
                        input1v3Sqr[i] = p2;
                    }

                    Vector3 p3 = new Vector3(x, y, z);
                    input1v3Cub[i] = p3;
                }
            }
        }

        switch (m_noiseType)
        {
        case NoiseType.Classic1D:
            offset[1] = offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                ClassicNoise.Compute(output1, scale[0], offset[0], m_numOctaves, m_octaveOffsetFactor);
                Draw(output1);
                break;

            case Mode.kGpuComputeCustomSamples:
                ClassicNoise.Compute(input1v2, output1, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v2, output1);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.Classic2D:
            offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                ClassicNoise.Compute(output2, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(output2);
                break;

            case Mode.kGpuComputeCustomSamples:
                ClassicNoise.Compute(input1v2Sqr, output1Sqr, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v2Sqr, output1Sqr);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.Classic3D:
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                ClassicNoise.Compute(output3, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(output3);
                break;

            case Mode.kGpuComputeCustomSamples:
                ClassicNoise.Compute(input1v3Cub, output1Cub, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v3Cub, output1Cub);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.ClassicPeriodic1D:
            offset[1] = offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                ClassicNoisePeriodic.Compute(output1, scale[0], offset[0], period[0], m_numOctaves, m_octaveOffsetFactor);
                Draw(output1);
                break;

            case Mode.kGpuComputeCustomSamples:
                ClassicNoisePeriodic.Compute(input1v2, output1, scale, offset, period, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v2, output1);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.ClassicPeriodic2D:
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                ClassicNoisePeriodic.Compute(output2, scale, offset, period, m_numOctaves, m_octaveOffsetFactor);
                Draw(output2);
                break;

            case Mode.kGpuComputeCustomSamples:
                offset[2] = 0.0f;
                ClassicNoisePeriodic.Compute(input1v2Sqr, output1Sqr, scale, offset, period, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v2Sqr, output1Sqr);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.ClassicPeriodic3D:
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                ClassicNoisePeriodic.Compute(output3, scale, offset, period, m_numOctaves, m_octaveOffsetFactor);
                Draw(output3);
                break;

            case Mode.kGpuComputeCustomSamples:
                ClassicNoisePeriodic.Compute(input1v3Cub, output1Cub, scale, offset, period, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v3Cub, output1Cub);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.Random1D:
            offset[1] = offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
            case Mode.kGpuComputeCustomSamples: // pointless
                RandomNoise.Compute(output1, seed);
                Draw(output1);
                break;

            case Mode.kCpu:
                for (int x = 0; x < output1.GetLength(0); ++x)
                {
                    output1[x] = RandomNoise.Get(x, seed);
                }
                Draw(output1);
                break;
            }
            break;

        case NoiseType.Random2D:
            offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
            case Mode.kGpuComputeCustomSamples: // pointless
                RandomNoise.Compute(output2, seed);
                Draw(output2);
                break;

            case Mode.kCpu:
                for (int y = 0; y < output2.GetLength(1); ++y)
                {
                    for (int x = 0; x < output2.GetLength(0); ++x)
                    {
                        output2[y, x] = RandomNoise.Get(new Vector2(x, y), seed);
                    }
                }
                Draw(output2);
                break;
            }
            break;

        case NoiseType.Random3D:
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
            case Mode.kGpuComputeCustomSamples: // pointless
                RandomNoise.Compute(output3, seed);
                break;

            case Mode.kCpu:
                for (int z = 0; z < output3.GetLength(2); ++z)
                {
                    for (int y = 0; y < output3.GetLength(1); ++y)
                    {
                        for (int x = 0; x < output3.GetLength(0); ++x)
                        {
                            output3[z, y, x] = RandomNoise.Get(new Vector3(x, y, z), seed);
                        }
                    }
                }
                break;
            }
            Draw(output3);
            break;

        case NoiseType.RandomVector1DVec2:
            offset[1] = offset[2] = 0.0f;
            RandomNoiseVector.Compute(output1v2, seed);
            Draw(output1v2);
            break;

        case NoiseType.RandomVector2DVec2:
            offset[2] = 0.0f;
            RandomNoiseVector.Compute(output2v2, seed);
            Draw(output2v2);
            break;

        case NoiseType.RandomVector1DVec3:
            offset[1] = offset[2] = 0.0f;
            RandomNoiseVector.Compute(output1v3, seed);
            Draw(output1v3);
            break;

        case NoiseType.RandomVector2DVec3:
            offset[2] = 0.0f;
            RandomNoiseVector.Compute(output2v3, seed);
            Draw(output2v3);
            break;

        case NoiseType.RandomVector3DVec3:
            RandomNoiseVector.Compute(output3v3, seed);
            Draw(output3v3);
            break;

        case NoiseType.Simplex1D:
            offset[1] = offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                SimplexNoise.Compute(output1, scale[0], offset[0], m_numOctaves, m_octaveOffsetFactor);
                Draw(output1);
                break;

            case Mode.kGpuComputeCustomSamples:
                SimplexNoise.Compute(input1v2, output1, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v2, output1);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.Simplex2D:
            offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                SimplexNoise.Compute(output2, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(output2);
                break;

            case Mode.kGpuComputeCustomSamples:
                SimplexNoise.Compute(input1v2Sqr, output1Sqr, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v2Sqr, output1Sqr);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.Simplex3D:
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                SimplexNoise.Compute(output3, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(output3);
                break;

            case Mode.kGpuComputeCustomSamples:
                SimplexNoise.Compute(input1v3Cub, output1Cub, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v3Cub, output1Cub);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.SimplexGradient1DVec2:
            offset[1] = offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                SimplexNoiseGradient.Compute(output1v2, scale[0], offset[0], m_numOctaves, m_octaveOffsetFactor);
                Draw(output1v2);
                break;

            case Mode.kGpuComputeCustomSamples:
                SimplexNoiseGradient.Compute(input1v2, output1v2, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v2, output1v2);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.SimplexGradient2DVec2:
            offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                SimplexNoiseGradient.Compute(output2v2, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(output2v2);
                break;

            case Mode.kGpuComputeCustomSamples:
                SimplexNoiseGradient.Compute(input1v2Sqr, output1v2Sqr, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v2Sqr, output1v2Sqr);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.SimplexGradient1DVec3:
            offset[1] = offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                SimplexNoiseGradient.Compute(output1v3, scale[0], offset[0], m_numOctaves, m_octaveOffsetFactor);
                Draw(output1v3);
                break;

            case Mode.kGpuComputeCustomSamples:
                SimplexNoiseGradient.Compute(input1v3, output1v3, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v3, output1v3);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.SimplexGradient2DVec3:
            offset[2] = 0.0f;
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                SimplexNoiseGradient.Compute(output2v3, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(output2v3);
                break;

            case Mode.kGpuComputeCustomSamples:
                SimplexNoiseGradient.Compute(input1v3Sqr, output1v3Sqr, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v3Sqr, output1v3Sqr);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;

        case NoiseType.SimplexGradient3DVec3:
            switch (m_mode)
            {
            case Mode.kGpuComputeGridSamples:
                SimplexNoiseGradient.Compute(output3v3, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(output3v3);
                break;

            case Mode.kGpuComputeCustomSamples:
                SimplexNoiseGradient.Compute(input1v3Cub, output1v3Cub, scale, offset, m_numOctaves, m_octaveOffsetFactor);
                Draw(input1v3Cub, output1v3Cub);
                break;

            case Mode.kCpu:
                // TODO
                break;
            }
            break;
        }
    }