private static Bitmap generateWaterMask(int facing, int variant)
        {
            setupCurrentColorsH(Color.FromArgb(100, 230, 250));
            Bitmap bmp = new Bitmap(vwidth * 16, vheight * 16, PixelFormat.Format32bppArgb);

            //            Bitmap bmp = new Bitmap(4 * 128 + 8, 2 * 128 + 8, PixelFormat.Format32bppArgb);

            // Specify a pixel format.
            PixelFormat pxf = PixelFormat.Format32bppArgb;

            // Lock the bitmap's bits.
            Rectangle  rect    = new Rectangle(0, 0, bmp.Width, bmp.Height);
            BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, pxf);

            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap.
            // int numBytes = bmp.Width * bmp.Height * 3;
            int numBytes = bmpData.Stride * bmp.Height;

            byte[] argbValues = new byte[numBytes];
            argbValues.Fill <byte>(0);
            byte[] outlineColors = new byte[numBytes];
            outlineColors.Fill <byte>(0);
            byte[] outlineValues = new byte[numBytes];
            outlineValues.Fill <byte>(0);
            bool[] barePositions = new bool[numBytes];
            barePositions.Fill(false);

            int[] xbuffer = new int[numBytes];
            xbuffer.Fill <int>(-999);
            int[] zbuffer = new int[numBytes];
            zbuffer.Fill <int>(-999);

            for (int mvdx = 15; mvdx >= 0; mvdx--)
            {
                for (int mvdy = 0; mvdy <= 15; mvdy++)
                {
                    MagicaVoxelData vx = new MagicaVoxelData {
                        x = (byte)mvdx, y = (byte)mvdy, z = 0, color = 153
                    };
                    int current_color = hcolorcount + 19;
                    //int unshaded = VoxelLogic.WithoutShadingK(vx.color);
                    //int current_color = ((255 - vx.color) % 4 == 0) ? (255 - vx.color) / 4 + hcolorcount : ((254 - vx.color) % 4 == 0) ? (253 - clear) / 4 : (253 - vx.color) / 4;
                    int p         = 0;
                    int mod_color = current_color;

                    for (int j = 0; j < vheight; j++)
                    {
                        for (int i = 0; i < 4 * vwidth; i++)
                        {
                            //p = 4 * ((vx.x + vx.y) * 2 + 2) + i + bmpData.Stride * (128 + 2 - vx.y + vx.x + j);
                            mod_color = current_color;
                            p         = voxelToPixelH16(i, j, vx.x, vx.y, 0, current_color, bmpData.Stride, 0, true);
                            if (argbValues[p] == 0)
                            {
                                zbuffer[p] = vx.z;
                                xbuffer[p] = vx.x;
                                if (i % 4 == 3)
                                {
                                    double wave = Simplex.FindNoiseFlatWater(facing, vx.x, vx.y, variant);

                                    if (wave > 0.73)
                                    {
                                        wave = 85 * wave;
                                    }
                                    else if (wave > 0.64)
                                    {
                                        wave = 65 * wave;
                                    }
                                    else if (wave > 0.55)
                                    {
                                        wave = 50 * wave;
                                    }
                                    else if (wave < 0.45)
                                    {
                                        wave += 0.2;
                                        if (wave < 0.5)
                                        {
                                            wave       = -15 / wave;
                                            mod_color -= hcolorcount;
                                        }
                                        else if (wave < 0.55)
                                        {
                                            wave       = -11 / wave;
                                            mod_color -= hcolorcount;
                                        }
                                        else if (wave < 0.6)
                                        {
                                            wave = -7 / wave;
                                            mod_color--;
                                        }
                                        else
                                        {
                                            wave = 6.0 * (wave - 0.25);
                                        }
                                    }
                                    else
                                    {
                                        wave = 32.0 * wave;
                                    }
                                    wave      = Clamp(wave, -72.0, 72.0);
                                    mod_color = (byte)(((int)(wave / 12.2)) * 2 + mod_color);


                                    argbValues[p - 3] = hrendered[mod_color][i - 3 + j * (vwidth * 4)];
                                    argbValues[p - 2] = hrendered[mod_color][i - 2 + j * (vwidth * 4)];
                                    argbValues[p - 1] = hrendered[mod_color][i - 1 + j * (vwidth * 4)];
                                    argbValues[p - 0] = 255;
                                    if (outlineColors[p] == 0)
                                    {
                                        outlineColors[p] = hrendered[mod_color][i + (4 * vwidth * vheight)];
                                    }
                                }
                            }
                        }
                    }
                }
            }

            /*
             * bool darkOutline = false;
             * for (int i = 3; i < numBytes; i += 4)
             * {
             *  if (argbValues[i] > 255 * waver_alpha && barePositions[i] == false)
             *  {
             *
             *      if (i + 4 >= 0 && i + 4 < argbValues.Length && argbValues[i + 4] == 0 && darkOutline && outlineValues[i + 4] == 0) { outlineValues[i + 4] = 255; } else if (i + 4 >= 0 && i + 4 < argbValues.Length && barePositions[i + 4] == false && (zbuffer[i] - 1 > zbuffer[i + 4] || xbuffer[i] - 1 > xbuffer[i + 4]) && outlineValues[i + 4] == 0) { outlineValues[i + 4] = 255; outlineValues[i + 4 - 1] = outlineColors[i - 1]; outlineValues[i + 4 - 2] = outlineColors[i - 2]; outlineValues[i + 4 - 3] = outlineColors[i - 3]; }
             *      if (i - 4 >= 0 && i - 4 < argbValues.Length && argbValues[i - 4] == 0 && darkOutline && outlineValues[i - 4] == 0) { outlineValues[i - 4] = 255; } else if (i - 4 >= 0 && i - 4 < argbValues.Length && barePositions[i - 4] == false && (zbuffer[i] - 1 > zbuffer[i - 4] || xbuffer[i] - 1 > xbuffer[i - 4]) && outlineValues[i - 4] == 0) { outlineValues[i - 4] = 255; outlineValues[i - 4 - 1] = outlineColors[i - 1]; outlineValues[i - 4 - 2] = outlineColors[i - 2]; outlineValues[i - 4 - 3] = outlineColors[i - 3]; }
             *      if (i + bmpData.Stride >= 0 && i + bmpData.Stride < argbValues.Length && argbValues[i + bmpData.Stride] == 0 && darkOutline && outlineValues[i + bmpData.Stride] == 0) { outlineValues[i + bmpData.Stride] = 255; } else if (i + bmpData.Stride >= 0 && i + bmpData.Stride < argbValues.Length && barePositions[i + bmpData.Stride] == false && (zbuffer[i] - 1 > zbuffer[i + bmpData.Stride] || xbuffer[i] - 1 > xbuffer[i + bmpData.Stride]) && outlineValues[i + bmpData.Stride] == 0) { outlineValues[i + bmpData.Stride] = 255; outlineValues[i + bmpData.Stride - 1] = outlineColors[i - 1]; outlineValues[i + bmpData.Stride - 2] = outlineColors[i - 2]; outlineValues[i + bmpData.Stride - 3] = outlineColors[i - 3]; }
             *      if (i - bmpData.Stride >= 0 && i - bmpData.Stride < argbValues.Length && argbValues[i - bmpData.Stride] == 0 && darkOutline && outlineValues[i - bmpData.Stride] == 0) { outlineValues[i - bmpData.Stride] = 255; } else if (i - bmpData.Stride >= 0 && i - bmpData.Stride < argbValues.Length && barePositions[i - bmpData.Stride] == false && (zbuffer[i] - 1 > zbuffer[i - bmpData.Stride] || xbuffer[i] - 1 > xbuffer[i - bmpData.Stride]) && outlineValues[i - bmpData.Stride] == 0) { outlineValues[i - bmpData.Stride] = 255; outlineValues[i - bmpData.Stride - 1] = outlineColors[i - 1]; outlineValues[i - bmpData.Stride - 2] = outlineColors[i - 2]; outlineValues[i - bmpData.Stride - 3] = outlineColors[i - 3]; }
             *  }
             *
             * }
             */


            for (int i = 3; i < numBytes; i += 4)
            {
                if (argbValues[i] > 0)
                {
                    argbValues[i] = 255;
                }
                if (outlineValues[i] == 255)
                {
                    argbValues[i]     = 255;
                    argbValues[i - 1] = outlineValues[i - 1];
                    argbValues[i - 2] = outlineValues[i - 2];
                    argbValues[i - 3] = outlineValues[i - 3];
                }
            }

            Marshal.Copy(argbValues, 0, ptr, numBytes);

            // Unlock the bits.
            bmp.UnlockBits(bmpData);

            return(bmp);
        }