private static HeightFieldGenerator ConvEnumToInstance(ConvolutionImplementation implementation)
    {
        HeightFieldGenerator heightFieldGenerator;

        switch (implementation)
        {
        case CONV_GPU_1D:
        {
            throw new NotImplementedException();
        }

        case CONV_GPU_2D:
        {
            heightFieldGenerator = new Convolution2DFastHeightFieldGenerator();
        }
        break;

        case CONV_CPU_1D:
        {
            throw new NotImplementedException();
        }

        case CONV_CPU_2D:
        {
            heightFieldGenerator = new GPUConvolution2DFastHeightFieldGenerator();
        }
        break;

        default:
        {
            throw new NotImplementedException();
        }
        }
        return(heightFieldGenerator);
    }
    override public void Initialise(ExtendedHeightField.HeightFieldInfo hf, ParticleContainer wp)
    {
        heightFieldInfo = hf;
        pointMap        = new ExtendedHeightField(hf.Width, hf.Height, hf.HoriRes, hf.VertRes);

        convolvedTexture            = new Texture2D(heightFieldInfo.HoriRes, heightFieldInfo.VertRes, TextureFormat.RGBAFloat, false);
        convolvedTexture.anisoLevel = 1;
        convolvedTexture.filterMode = FilterMode.Point;
        convolvedTexture.wrapMode   = TextureWrapMode.Clamp;
        convolvedTexture.name       = "Convolved Texture";

        shaderTexture = new RenderTexture(heightFieldInfo.HoriRes, heightFieldInfo.VertRes, 24, RenderTextureFormat.ARGBFloat);
        shaderTexture.antiAliasing     = 1;
        shaderTexture.anisoLevel       = 0;
        shaderTexture.autoGenerateMips = false;
        shaderTexture.wrapMode         = TextureWrapMode.Clamp;
        shaderTexture.filterMode       = FilterMode.Point;


        int kernelWidth  = Mathf.CeilToInt((WaveParticle.RADIUS / heightFieldInfo.Width) * heightFieldInfo.HoriRes);
        int kernelHeight = Mathf.CeilToInt((WaveParticle.RADIUS / heightFieldInfo.Height) * heightFieldInfo.VertRes);

        Color[] kernelArray = Convolution2DFastHeightFieldGenerator.creatKernel(kernelHeight, kernelWidth, heightFieldInfo);

        kernel = new Texture2D(kernelWidth, kernelHeight, TextureFormat.RGBAFloat, false);
        kernel.SetPixels(kernelArray);
        kernel.Apply();

        convolutionMaterial = new Material(Shader.Find("Unlit/2DFunction"));
        convolutionMaterial.SetTexture(Shader.PropertyToID("_KernelTex"), kernel);
        convolutionMaterial.SetFloat(Shader.PropertyToID("_Width"), heightFieldInfo.Width);
        convolutionMaterial.SetFloat(Shader.PropertyToID("_Height"), heightFieldInfo.Height);
        convolutionMaterial.SetInt(Shader.PropertyToID("_HoriRes"), heightFieldInfo.HoriRes);
        convolutionMaterial.SetInt(Shader.PropertyToID("_VertRes"), heightFieldInfo.VertRes);
        convolutionMaterial.SetFloat(Shader.PropertyToID("_ParticleRadii"), WaveParticle.RADIUS);
        convolutionMaterial.SetFloat(Shader.PropertyToID("_KernelWidth"), kernelWidth);
        convolutionMaterial.SetFloat(Shader.PropertyToID("_KernelHeight"), kernelHeight);

        waveParticles = wp;
    }
    public static HeightFieldGenerator CreateAndInitialise(Choice hfge, ExtendedHeightField.HeightFieldInfo heightFieldInfo, ParticleContainer waveParticles)
    {
        HeightFieldGenerator heightFieldGenerator;

        switch (hfge)
        {
        case Choice.GPU_CONVOLUTION_2D:
        {
            heightFieldGenerator = new GPUConvolution2DFastHeightFieldGenerator();
        }
        break;

        case Choice.CPU_CONVOLUTION_2D:
        {
            heightFieldGenerator = new Convolution2DFastHeightFieldGenerator();
        }
        break;

        case Choice.PRECISE:
        {
            heightFieldGenerator = new PreciseHeightFieldGenerator();
        }
        break;

        case Choice.NONE:
        {
            heightFieldGenerator = new EmptyHeightFieldGenerator();
        }
        break;

        default:
        {
            // TODO: throw an appropriate exception!
            throw new System.Exception();
        }
        }
        heightFieldGenerator.Initialise(heightFieldInfo, waveParticles);
        return(heightFieldGenerator);
    }