protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            Closed += ShaderTest_Closed;

            gl3dcontroller = new Controller3D();
            gl3dcontroller.PaintObjects = ControllerDraw;
            gl3dcontroller.ZoomDistance = 100F;
            gl3dcontroller.MatrixCalc.PerspectiveNearZDistance = 0.1f;
            glwfc.BackColor = Color.FromArgb(0, 0, 20);
            gl3dcontroller.Start(glwfc, new Vector3(0, 0, 0), new Vector3(120f, 0, 0f), 1F);
            gl3dcontroller.KeyboardTravelSpeed = (ms, eyedist) =>
            {
                return((float)ms / 20.0f);
            };

            // this bit is eye candy just to show its working

            items.Add(new GLColorShaderWorld(), "COSW");
            GLRenderState rl = GLRenderState.Lines(1);

            rObjects.Add(items.Shader("COSW"),
                         GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, rl,
                                                              GLShapeObjectFactory.CreateLines(new Vector3(-40, 0, -40), new Vector3(-40, 0, 40), new Vector3(10, 0, 0), 9),
                                                              new Color4[] { Color.Red, Color.Red, Color.Green, Color.Green })
                         );


            rObjects.Add(items.Shader("COSW"),
                         GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, rl,
                                                              GLShapeObjectFactory.CreateLines(new Vector3(-40, 0, -40), new Vector3(40, 0, -40), new Vector3(0, 0, 10), 9),
                                                              new Color4[] { Color.Red, Color.Red, Color.Green, Color.Green })
                         );


            items.Add(new GLTexture2D(Properties.Resources.moonmap1k, SizedInternalFormat.Rgba8), "moon");
            items.Add(new GLTexturedShaderObjectTranslation(), "TEX");

            items.Add(new GLMatrixCalcUniformBlock(), "MCUB");     // def binding of 0

            // Pass vertex data thru a vertex shader which stores into a block

            vecoutbuffer = new GLStorageBlock(30, true);
            vecoutbuffer.AllocateBytes(32000, OpenTK.Graphics.OpenGL4.BufferUsageHint.DynamicCopy);       // set size of vec buffer

            ComputeShader csn = new ComputeShader();

            csn.Run();
            GLMemoryBarrier.All();

            // test consistency between row/columns of matrix4 of code and glsl
            int count = vecoutbuffer.ReadInt(0);

            System.Diagnostics.Debug.WriteLine("Count is " + count);

            {
                float[] mat4 = vecoutbuffer.ReadFloats(16, 16);
                System.Diagnostics.Debug.WriteLine("Compare mat4 constructor via order of floats:");
                for (int i = 0; i < mat4.Length; i++)
                {
                    System.Diagnostics.Debug.Write(string.Format("{0} = {1}, ", i, mat4[i]));
                }
                System.Diagnostics.Debug.WriteLine("");
            }

            {
                Vector2[] vec2 = vecoutbuffer.ReadVector2s(4, 2);
                System.Diagnostics.Debug.WriteLine($"Vec2a = inc {vec2[0].X.Degrees()} az {vec2[0].Y.Degrees()}");
            }

            Matrix4[] mat4r = vecoutbuffer.ReadMatrix4s(32, 32); // read all matrixes

            System.Diagnostics.Debug.WriteLine("Test mat constructor =" + Environment.NewLine + mat4r[0].ToString());
            System.Diagnostics.Debug.WriteLine("Row0 is " + mat4r[0].Row0.ToString());
            System.Diagnostics.Debug.WriteLine("Should be 20000 = " + mat4r[0][2, 3]);

            int id = 1;

            System.Diagnostics.Debug.WriteLine("Identity matrix = " + Environment.NewLine + mat4r[id++].ToString());

            {
                Matrix4 xrotpi4 = Matrix4.CreateRotationX(0.7853f);     // demo that Matrix4.Create is the same values as mat4rotatex
                System.Diagnostics.Debug.WriteLine("Rotate X Pi/4 =" + GLStaticsMatrix4.ApproxEquals(mat4r[id], xrotpi4) + Environment.NewLine + mat4r[id].ToString());
                id++;
            }

            {
                Matrix4 yrotpi4 = Matrix4.CreateRotationY(0.7853f);
                System.Diagnostics.Debug.WriteLine("Rotate Y Pi/4 =" + GLStaticsMatrix4.ApproxEquals(mat4r[id], yrotpi4) + Environment.NewLine + mat4r[id].ToString());
                id++;
            }

            {
                Matrix4 zrotpi4 = Matrix4.CreateRotationZ(0.7853f);
                System.Diagnostics.Debug.WriteLine("Rotate Z Pi/4 =" + GLStaticsMatrix4.ApproxEquals(mat4r[4], zrotpi4) + Environment.NewLine + mat4r[4].ToString());
                id++;
            }

            {   // test:
                //Matrix4 xrot = Matrix4.CreateRotationX((float)(Math.PI / 2));
                //Matrix4 r1 = new Matrix4(0, 0, 0, 0,
                //                         0, 0, 0, 0,
                //                         0, 0, 1, 0,
                //                         0, 0, 0, 1);
                //r1 = new Matrix4(new Matrix3())
                //Matrix4 r2 = r1 * xrot;
                //System.Diagnostics.Debug.WriteLine($"rotate z=+1 around x by 90\n{r1}\n{r2} ");
            }
            // X Y
            {
                Matrix4 xrot = Matrix4.CreateRotationX(0.7853f);     // demo that Matrix4.Create is the same values as mat4rotatex
                Matrix4 yrot = Matrix4.CreateRotationY(0.5f);
                Matrix4 res  = Matrix4.Identity;
                res = res * xrot;
                res = res * yrot;
                System.Diagnostics.Debug.WriteLine("Rotate XY Manu =" + GLStaticsMatrix4.ApproxEquals(mat4r[id], res) + Environment.NewLine + mat4r[id].ToString());
                id++;
                System.Diagnostics.Debug.WriteLine("Rotate XY Auto =" + GLStaticsMatrix4.ApproxEquals(mat4r[id], res) + Environment.NewLine + mat4r[id].ToString());
                id++;
                res = Matrix4.Identity;
                res = res * yrot;
                res = res * xrot;
                System.Diagnostics.Debug.WriteLine("Rotate YX Manu =" + GLStaticsMatrix4.ApproxEquals(mat4r[id], res) + Environment.NewLine + mat4r[id].ToString());
                id++;
                System.Diagnostics.Debug.WriteLine("Rotate YX Auto =" + GLStaticsMatrix4.ApproxEquals(mat4r[id], res) + Environment.NewLine + mat4r[id].ToString());
                id++;
            }

            // mat4 translation
            {
                Matrix4 trans = Matrix4.CreateTranslation(10, 20, 30);
                System.Diagnostics.Debug.WriteLine("Translation =" + GLStaticsMatrix4.ApproxEquals(mat4r[id], trans) + Environment.NewLine + mat4r[id].ToString());
                id++;
            }

            // mat4translation with matrix
            {
                Matrix4 yrot05       = Matrix4.CreateRotationY(0.5f);
                Matrix4 trans        = Matrix4.CreateTranslation(10, 20, 30);
                Matrix4 rotplustrans = Matrix4.Mult(yrot05, trans);
                System.Diagnostics.Debug.WriteLine("Rot Translation =" + GLStaticsMatrix4.ApproxEquals(mat4r[id], rotplustrans) + Environment.NewLine + mat4r[id].ToString());
                id++;
            }

            {
                Matrix4 trans   = Matrix4.CreateTranslation(10, 20, 30);
                Matrix4 rotxm90 = Matrix4.CreateRotationX(-90f.Radians());
                Matrix4 roty90  = Matrix4.CreateRotationY(90f.Radians());
                Matrix4 mscale  = Matrix4.CreateScale(1, 2, 3);

                Matrix4 res = Matrix4.Identity;
                res = res * mscale;
                res = res * rotxm90;
                res = res * roty90;
                res = res * trans;
                System.Diagnostics.Debug.WriteLine("Trans rot scale =" + GLStaticsMatrix4.ApproxEquals(mat4r[id], res) + Environment.NewLine + mat4r[id].ToString());
                id++;
                //System.Diagnostics.Debug.WriteLine(transrotscale.ToString());

                System.Diagnostics.Debug.WriteLine("Trans rot scale2 =" + GLStaticsMatrix4.ApproxEquals(mat4r[id], res) + Environment.NewLine + mat4r[id].ToString());
                id++;
            }


            Vector4[] vec4r = vecoutbuffer.ReadVector4s(32 + 13 * 64, 2); // read all vec4 (N matrices between)

            {
                System.Diagnostics.Debug.WriteLine($"Vec4 {vec4r[0]}");
            }



            {
                StringMatrix rox = new StringMatrix("1", "0", "0", "0",
                                                    "0", "cx", "sx", "0",
                                                    "0", "-sx", "cx", "0",
                                                    "0", "0", "0", "1");
                StringMatrix roxm90 = new StringMatrix("1", "0", "0", "0",
                                                       "0", "0", "-1", "0",
                                                       "0", "1", "0", "0",
                                                       "0", "0", "0", "1");
                StringMatrix roy = new StringMatrix("cy", "0", "-sy", "0",
                                                    "0", "1", "0", "0",
                                                    "sy", "0", "cy", "0",
                                                    "0", "0", "0", "1");
                StringMatrix res = StringMatrix.Mult(roxm90, roy);
                string       r   = res.ToString(true);
                System.Diagnostics.Debug.WriteLine($"{r}");
                r = res.ToList();
                System.Diagnostics.Debug.WriteLine($"{r}");

                res = StringMatrix.Mult(rox, roy);
                r   = res.ToString(true);
                System.Diagnostics.Debug.WriteLine($"{r}");

                StringVector4 v4a   = new StringVector4("a", "-1", "c", "d");
                StringVector4 resv4 = StringMatrix.Mult(rox, v4a);
                r = resv4.ToString(true);
                System.Diagnostics.Debug.WriteLine($"{r}");
            }


            //    System.Di
            //    agnostics.Debug.WriteLine(rotplustransscale.ToString());
        }