private GLObject PrepareCube()
        {
            float[] vertices = new float[] {
                //X     Y      Z     R      G    B     U     V
                -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
                 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
                 0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
                 0.5f,  0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
                -0.5f,  0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
                -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,

                -0.5f, -0.5f,  0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
                 0.5f, -0.5f,  0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
                 0.5f,  0.5f,  0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
                 0.5f,  0.5f,  0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
                -0.5f,  0.5f,  0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
                -0.5f, -0.5f,  0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,

                -0.5f,  0.5f,  0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
                -0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
                -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
                -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
                -0.5f, -0.5f,  0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
                -0.5f,  0.5f,  0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,

                 0.5f,  0.5f,  0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
                 0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
                 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
                 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
                 0.5f, -0.5f,  0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
                 0.5f,  0.5f,  0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,

                -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
                 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
                 0.5f, -0.5f,  0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
                 0.5f, -0.5f,  0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                -0.5f, -0.5f,  0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
                -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,

                -0.5f,  0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
                 0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
                 0.5f,  0.5f,  0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
                 0.5f,  0.5f,  0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
                -0.5f,  0.5f,  0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
                -0.5f,  0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,

                -1.0f, -1.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
                 1.0f, -1.0f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
                 1.0f,  1.0f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
                 1.0f,  1.0f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
                -1.0f,  1.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
                -1.0f, -1.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
            };

            // Make shader
            var program1 = new ShaderProgram();
            program1.AddShader(new Shader(ShaderType.VertexShader, LoadShader("Shaders/basic.vert")));
            program1.AddShader(new Shader(ShaderType.FragmentShader, LoadShader("Shaders/basic.frag")));

            // Make textures
            var tex1 = new Texture(new Bitmap(GetResourceStream("Assets/info.png")), TextureTarget.Texture2D, PixelInternalFormat.Rgba, 0);

            tex1.TexParameter(TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
            tex1.TexParameter(TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
            tex1.TexParameter(TextureParameterName.TextureMinFilter, (int)TextureMinFilter.NearestMipmapLinear);
            tex1.TexParameter(TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

            // Create mipmap (pre-rendered thumb)
            GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);

            var tex2 = new Texture(new Bitmap(GetResourceStream("Assets/play.png")), TextureTarget.Texture2D, PixelInternalFormat.Rgba, 1);

            tex2.TexParameter(TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
            tex2.TexParameter(TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
            tex2.TexParameter(TextureParameterName.TextureMinFilter, (int)TextureMinFilter.NearestMipmapLinear);
            tex2.TexParameter(TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

            // Create mipmap (pre-rendered thumb)
            GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);

            List<PartitionRule> rules = new List<PartitionRule>()
            {
                new PartitionRule("position", 0, 3),
                new PartitionRule("color", 3, 3),
                new PartitionRule("texcoord", 6, 2)
            };

            GLObject obj = new GLObject(vertices, rules, program1);
            obj.AddTexture("tex1", tex1);
            obj.AddTexture("tex2", tex2);

            return obj;
        }
        private GLObject MakeObject(Image img)
        {
            int width = img.Width;
            int height = img.Height;
            int stride = 4;
            Vector2[] vertices = MakePlane(width, height, width /2, height / 2);
            float[] data = new float[vertices.Length * stride];

            for (int i = 0; i < vertices.Length; i++)
            {
                int j = i * stride;
                Vector2 v = vertices[i];

                // X / Z
                data[j] = v.X;
                data[j+1] = v.Y;

                // U / V
                data[j + 2] = v.X / width;
                data[j + 3] = -v.Y / height;
            }

            Matrix4 model = Matrix4.Identity;//Matrix4.CreateRotationX(3.41f);
            camera = Matrix4.LookAt(new Vector3(700, 700, -400), new Vector3(600, 0, -300), new Vector3(0, 1, 0));
            Matrix4 proj = Matrix4.CreatePerspectiveFieldOfView(3.41f / 4, Width / (float)Height, 0.1f, 10000);

            // Calc shader
            ShaderProgram program = new ShaderProgram();
            program.AddShader(new Shader(ShaderType.VertexShader, Helper.LoadShader("Shaders/picture.vert")));
            program.AddShader(new Shader(ShaderType.FragmentShader, Helper.LoadShader("Shaders/picture.frag")));

            if (!program.Compile())
            {
                throw new Exception(program.Log);
            }

            program.UniformMatrix4("model", false, ref model);
            program.UniformMatrix4("view", false, ref camera);
            program.UniformMatrix4("projection", false, ref proj);

            Texture image = new Texture(img, TextureTarget.Texture2D, PixelInternalFormat.Rgb, 0);
            image.TexParameter(TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            image.TexParameter(TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
            image.TexParameter(TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
            image.TexParameter(TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);

            // Make instance
            GLObject obj = new GLObject(data, new List<PartitionRule>()
            {
                new PartitionRule("position", 0, 2),
                new PartitionRule("texcoord", 2, 2)
            }, program);

            obj.AddTexture("image", image);
            return obj;
        }