private void OnLoad(object sender, EventArgs e)
        {
            // initialize and bind framebuffer
            _framebuffer = new Framebuffer();
            _framebuffer.Bind(FramebufferTarget.Framebuffer);

            // initialize a renderbuffer and bind it to the depth attachment
            // to support depth testing while rendering to the texture
            _depthBuffer = new Renderbuffer();
            _depthBuffer.Init(RenderbufferStorage.DepthComponent, FramebufferWidth, FramebufferHeight);
            _framebuffer.Attach(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, _depthBuffer);

            // initialize texture and bind it to the color attachment
            _texture = new Texture2D(SizedInternalFormat.Rgba8, FramebufferWidth, FramebufferHeight, 1);
            _framebuffer.Attach(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, _texture);
            Framebuffer.Unbind(FramebufferTarget.Framebuffer);

            // initialize demonstration geometry
            _cube = new ColorCube();
            _cube.UpdateBuffers();
            _quad = new TexturedQuad();
            _quad.UpdateBuffers();

            // initialize shaders
            _colorProgram = ProgramFactory.Create<SimpleColorProgram>();
            _textureProgram = ProgramFactory.Create<SimpleTextureProgram>();

            // set up vertex attributes for the cube
            _cubeVao = new VertexArray();
            _cubeVao.Bind();
            _cubeVao.BindAttribute(_colorProgram.InPosition, _cube.VertexBuffer);
            _cubeVao.BindAttribute(_colorProgram.InColor, _cube.ColorBuffer);
            _cubeVao.BindElementBuffer(_cube.IndexBuffer);

            // set up vertex attributes for the quad
            _quadVao = new VertexArray();
            _quadVao.Bind();
            _quadVao.BindAttribute(_textureProgram.InPosition, _quad.VertexBuffer);
            _quadVao.BindAttribute(_textureProgram.InTexCoord, _quad.TexCoordBuffer);

            // set camera position
            Camera.DefaultState.Position = new Vector3(0,0,3);
            Camera.ResetToDefault();

            // enable depth testing
            GL.Enable(EnableCap.DepthTest);
        }
        protected void OnLoad(object sender, EventArgs eventArgs)
        {
            VSync = VSyncMode.Off;

            // Check for necessary capabilities:
            var extensions = GL.GetString(StringName.Extensions);
            if (!GL.GetString(StringName.Extensions).Contains("GL_ARB_shading_language"))
            {
                throw new NotSupportedException(String.Format("This example requires OpenGL 2.0. Found {0}. Aborting.",
                    GL.GetString(StringName.Version).Substring(0, 3)));
            }

            if (!extensions.Contains("GL_ARB_texture_compression") ||
                 !extensions.Contains("GL_EXT_texture_compression_s3tc"))
            {
                throw new NotSupportedException("This example requires support for texture compression. Aborting.");
            }

            var temp = new int[1];
            GL.GetInteger(GetPName.MaxTextureImageUnits, out temp[0]);
            Trace.WriteLine(temp[0] + " TMU's for Fragment Shaders found. (2 required)");

            GL.GetInteger(GetPName.MaxVaryingFloats, out temp[0]);
            Trace.WriteLine(temp[0] + " varying floats between VS and FS allowed. (6 required)");

            GL.GetInteger(GetPName.MaxVertexUniformComponents, out temp[0]);
            Trace.WriteLine(temp[0] + " uniform components allowed in Vertex Shader. (6 required)");

            GL.GetInteger(GetPName.MaxFragmentUniformComponents, out temp[0]);
            Trace.WriteLine(temp[0] + " uniform components allowed in Fragment Shader. (11 required)");
            Trace.WriteLine("");

            // load textures
            TextureLoaderParameters.MagnificationFilter = TextureMagFilter.Linear;
            TextureLoaderParameters.MinificationFilter = TextureMinFilter.LinearMipmapLinear;
            TextureLoaderParameters.WrapModeS = TextureWrapMode.ClampToBorder;
            TextureLoaderParameters.WrapModeT = TextureWrapMode.ClampToBorder;
            TextureLoaderParameters.EnvMode = TextureEnvMode.Modulate;

            uint handle;
            TextureTarget target;
            ImageDDS.LoadFromDisk(TextureDiffuseHeightFilename, out handle, out target);
            _textureDiffuseHeight = TextureFactory.AquireTexture2D((int) handle);
            Trace.WriteLine("Loaded " + TextureDiffuseHeightFilename + " with handle " + handle + " as " + target);

            ImageDDS.LoadFromDisk(TextureNormalGlossFilename, out handle, out target);
            _textureNormalGloss = TextureFactory.AquireTexture2D((int) handle);
            Trace.WriteLine("Loaded " + TextureNormalGlossFilename + " with handle " + handle + " as " + target);

            Trace.WriteLine("End of Texture Loading. GL Error: " + GL.GetError());
            Trace.WriteLine("");

            // initialize buffer
            var normal = Vector3.UnitZ;
            var tangent = Vector3.UnitX;
            var vertices = new[]
            {
                new Vertex
                {
                    Position = new Vector3(-1,-1,0),
                    TexCoord = new Vector2(0,0),
                    Normal = normal,
                    Tangent = tangent
                },
                new Vertex
                {
                    Position = new Vector3(1,-1,0),
                    TexCoord = new Vector2(1,0),
                    Normal = normal,
                    Tangent = tangent
                },
                new Vertex
                {
                    Position = new Vector3(-1,1,0),
                    TexCoord = new Vector2(0,1),
                    Normal = normal,
                    Tangent = tangent
                },
                new Vertex
                {
                    Position = new Vector3(1,1,0),
                    TexCoord = new Vector2(1,1),
                    Normal = normal,
                    Tangent = tangent
                }
            };
            _buffer = new Buffer<Vertex>();
            _buffer.Init(BufferTarget.ArrayBuffer, vertices);

            // load shader
            _program = ProgramFactory.Create<ParallaxProgram>();
            _program.Use();

            // set up vertex array
            _vao = new VertexArray();
            _vao.Bind();
            // bind vertex attributes
            // the buffer layout is defined by the Vertex struct:
            //   data X Y Z NX NY NZ TX TY TZ  U  V *next vertex*
            // offset 0 4 8 12 16 20 24 28 32 36 40      44
            // having to work with offsets could be prevented by using seperate buffer objects for each attribute,
            // but that might reduce performance and can get annoying as well.
            // performance increase could also be achieved by improving coherent read access
            // by padding the struct so that each attribute begins at a multiple of 16 bytes, i.e. 4-floats
            // because the GPU can then read all 4 floats at once. I did not do that here to keep it simple.
            _vao.BindAttribute(_program.InPosition, _buffer);
            _vao.BindAttribute(_program.InNormal, _buffer, 12);
            _vao.BindAttribute(_program.InTangent, _buffer, 24);
            _vao.BindAttribute(_program.InTexCoord, _buffer, 36);

            // set camera position
            Camera.DefaultState.Position = new Vector3(0,0,3);
            Camera.ResetToDefault();

            // set state
            GL.ClearColor(0.2f, 0f, 0.4f, 0f);
            GL.PointSize(10f);
            GL.Disable(EnableCap.Dither);
            GL.FrontFace(FrontFaceDirection.Ccw);
            GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
            GL.PolygonMode(MaterialFace.Back, PolygonMode.Line);
        }
 /// <summary>
 /// Creates a new Texture2D instance compatible to the given bitmap.
 /// </summary>
 /// <param name="bitmap">Specifies the bitmap to which the new texture will be compatible.</param>
 /// <param name="texture">Outputs the newly created texture.</param>
 /// <param name="levels">Specifies the number of mipmap levels.</param>
 public static void CreateCompatible(Bitmap bitmap, out Texture2D texture, int levels = 0)
 {
     texture = new Texture2D(BitmapFormat.Get(bitmap).InternalFormat, bitmap.Width, bitmap.Height, levels);
 }