/// <summary> /// Initializes a new OpenGLTexture class. /// </summary> /// <param name="bitmap">The Bitmap.</param> internal OpenGLTexture(Bitmap bitmap) { Height = bitmap.Height; Width = bitmap.Width; BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); Id = OpenGLInterops.GenTexture(); OpenGLInterops.BindTexture(OpenGLInterops.GL_TEXTURE_2D, Id); OpenGLInterops.TexParameterI(OpenGLInterops.GL_TEXTURE_2D, OpenGLInterops.GL_TEXTURE_WRAP_S, (int)OpenGLInterops.GL_REPEAT); OpenGLInterops.TexParameterI(OpenGLInterops.GL_TEXTURE_2D, OpenGLInterops.GL_TEXTURE_WRAP_T, (int)OpenGLInterops.GL_REPEAT); OpenGLInterops.TexParameterF(OpenGLInterops.GL_TEXTURE_2D, OpenGLInterops.GL_TEXTURE_MIN_FILTER, SGL.SpriteBatch.InterpolationMode == InterpolationMode.Linear ? OpenGLInterops.GL_LINEAR : OpenGLInterops.GL_NEAREST); OpenGLInterops.TexParameterF(OpenGLInterops.GL_TEXTURE_2D, OpenGLInterops.GL_TEXTURE_MAG_FILTER, SGL.SpriteBatch.InterpolationMode == InterpolationMode.Linear ? OpenGLInterops.GL_LINEAR : OpenGLInterops.GL_NEAREST); OpenGLInterops.TexImage2D(OpenGLInterops.GL_TEXTURE_2D, OpenGLInterops.GL_RGBA, Width, Height, OpenGLInterops.GL_BGRA, OpenGLInterops.GL_UNSIGNED_BYTE, data.Scan0); OpenGLInterops.BindTexture(OpenGLInterops.GL_TEXTURE_2D, 0); bitmap.UnlockBits(data); bitmap.Dispose(); }
/// <summary> /// Swaps the buffers. /// </summary> public void SwapBuffers() { if (_deviceContext != IntPtr.Zero || _windowHandle != IntPtr.Zero) { OpenGLInterops.SwapBuffers(_deviceContext); } }
/// <summary> /// Throws the last error. /// </summary> public static void ThrowLastError() { var glError = OpenGLInterops.GetError(); if (glError != OpenGLError.GL_NO_ERROR) { throw new GraphicsException(glError.ToString()); } }
/// <summary> /// Locks the texture. /// </summary> public void Lock() { IsLocked = true; _lockedColors = new List <ColorData>(); _lockedData = new byte[Width * Height * 4]; Bind(); OpenGLInterops.GetTexImage(OpenGLInterops.GL_TEXTURE_2D, OpenGLInterops.GL_RGBA, OpenGLInterops.GL_UNSIGNED_BYTE, _lockedData); Unbind(); }
/// <summary> /// Disposes the object. /// </summary> /// <param name="disposing">The disposing state.</param> protected void Dispose(bool disposing) { try { OpenGLInterops.DeleteBuffers(1, new[] { Id }); } catch { LogManager.GetClassLogger().Warn("Unable to dispose."); } }
/// <summary> /// Initializes a new VertexArray class. /// </summary> public VertexArray() { var buffers = new uint[1]; OpenGLInterops.GenVertexArrays(1, buffers); if (buffers[0] == 0) { throw new GraphicsException("Unable to allocate memory for vertex array."); } Id = buffers[0]; }
/// <summary> /// Initializes a new IndexBuffer class. /// </summary> public IndexBuffer() { var buffers = new uint[1]; OpenGLInterops.GenBuffers(1, buffers); if (buffers[0] == 0) { throw new GraphicsException("Unable to allocate memory for index buffer."); } Id = buffers[0]; }
/// <summary> /// Disposes the object. /// </summary> /// <param name="disposing">The disposing state.</param> public virtual void Dispose(bool disposing) { OpenGLInterops.ReleaseDC(_windowHandle, _deviceContext); if (_renderContext != IntPtr.Zero) { OpenGLInterops.wglDeleteContext(_renderContext); _renderContext = IntPtr.Zero; } if (disposing) { } }
/// <summary> /// Draws a Texture. /// </summary> /// <param name="texture">The Texture.</param> /// <param name="rectangle">The Rectangle.</param> /// <param name="opacity">The Opacity.</param> /// <param name="color">The Color.</param> public void DrawTexture(ITexture texture, Rectangle rectangle, Color color, float opacity = 1) { var tex = texture as OpenGLTexture; if (tex == null) { throw new ArgumentException("Expected OpenGLTexture as resource."); } OpenGLColor col = OpenGLHelper.ConvertColor(color); var vertices = new[] { // Position Color Texcoords rectangle.X, rectangle.Y, col.R, col.G, col.B, 0.0f, 0.0f, // Top-left rectangle.X + rectangle.Width, rectangle.Y, col.R, col.G, col.B, 1.0f, 0.0f, // Top-right rectangle.X + rectangle.Width, rectangle.Y + tex.Height, col.R, col.G, col.B, 1.0f, 1.0f, // Bottom-right rectangle.X, rectangle.Y + rectangle.Height, col.R, col.G, col.B, 0.0f, 1.0f // Bottom-left }; _sourceVbo.SetData(vertices); tex.Bind(); _colorShader.SetUniform("dim", _graphicsDevice.BackBuffer.Width, _graphicsDevice.BackBuffer.Height, opacity); _colorShader.SetUniformMatrix("transform", _matrix4); uint posAttrib = _colorShader.GetAttribLocation("position"); VertexBuffer.EnableVertexAttribArray(posAttrib); VertexBuffer.VertexAttribPointer(posAttrib, 2, false, 7 * sizeof(float), 0); uint colAttrib = _colorShader.GetAttribLocation("color"); VertexBuffer.EnableVertexAttribArray(colAttrib); VertexBuffer.VertexAttribPointer(colAttrib, 3, false, 7 * sizeof(float), 2 * sizeof(float)); uint texAttrib = _colorShader.GetAttribLocation("texcoord"); VertexBuffer.EnableVertexAttribArray(texAttrib); VertexBuffer.VertexAttribPointer(texAttrib, 2, false, 7 * sizeof(float), 5 * sizeof(float)); OpenGLInterops.DrawElements(OpenGLInterops.GL_TRIANGLES, 6, OpenGLInterops.GL_UNSIGNED_SHORT, IntPtr.Zero); tex.Unbind(); }
/// <summary> /// Unlocks the data. /// </summary> public void Unlock() { _lockedData = null; Bind(); foreach (ColorData colordata in _lockedColors) { var pixelData = new byte[4]; pixelData[0] = colordata.Color.R; pixelData[1] = colordata.Color.G; pixelData[2] = colordata.Color.B; pixelData[3] = colordata.Color.A; OpenGLInterops.TexSubImage2D(OpenGLInterops.GL_TEXTURE_2D, 0, (int)colordata.Position.X, (int)colordata.Position.Y, 1, 1, OpenGLInterops.GL_RGBA, OpenGLInterops.GL_UNSIGNED_BYTE, pixelData); } Unbind(); IsLocked = false; }
/// <summary> /// Initializes the renderer. /// </summary> public void Initialize() { _renderContext.Initialize(); _colorShader = new ShaderProgram(); var vshader = new VertexShader(); vshader.Compile(SimpleVertexShader.SourceCode); var fshader = new FragmentShader(); fshader.Compile(SimpleFragmentShader.SourceCode); _colorShader.Link(vshader, fshader); OpenGLInterops.Enable(OpenGLInterops.GL_BLEND); OpenGLInterops.AlphaBlend(); SetTransform(Matrix2x3.Identity); OpenGLColor clearColor = OpenGLHelper.ConvertColor(_graphicsDevice.ClearColor); OpenGLInterops.ClearColor(clearColor); _windowSize = _window.Size; OpenGLInterops.Viewport(0, 0, (int)_windowSize.X, (int)_windowSize.Y); _sourceVao = new VertexArray(); _sourceVao.Bind(); _colorShader.Bind(); _sourceEbo = new IndexBuffer(); var elements = new ushort[] { 0, 1, 2, 2, 3, 0 }; _sourceEbo.Bind(); _sourceEbo.SetData(elements); _sourceVbo = new VertexBuffer(); _sourceVbo.Bind(); _graphicsDevice.ClearColorChanged += GraphicsDeviceClearColorChanged; _window.ScreenSizeChanged += WindowScreenSizeChanged; }
/// <summary> /// Triggered if the clear color changed. /// </summary> private void GraphicsDeviceClearColorChanged(object sender, EventArgs e) { OpenGLColor clearColor = OpenGLHelper.ConvertColor(_graphicsDevice.ClearColor); OpenGLInterops.ClearColor(clearColor); }
/// <summary> /// Begins the draw operation. /// </summary> public void Begin() { _renderContext.MakeCurrent(); OpenGLInterops.Clear(); }
/// <summary> /// Initializes the RenderContext. /// </summary> public void Initialize() { _windowHandle = SGL.QueryComponents <RenderTarget>().Handle; _deviceContext = NativeMethods.GetDC(_windowHandle); var pfd = new PixelFormatDescriptor(); pfd.Size = (short)Marshal.SizeOf(pfd); pfd.Version = 1; pfd.FormatDescription = PixelFormatDescription.DrawToWindow | PixelFormatDescription.SupportOpenGL | PixelFormatDescription.DoubleBuffer; pfd.PixelType = 0; pfd.ColorBits = 24; pfd.RedBits = 0; pfd.RedShift = 0; pfd.GreenBits = 0; pfd.GreenShift = 0; pfd.BlueBits = 0; pfd.BlueShift = 0; pfd.AlphaBits = 0; pfd.AlphaShift = 0; pfd.AccumBits = 0; pfd.AccumRedBits = 0; pfd.AccumGreenBits = 0; pfd.AccumBlueBits = 0; pfd.AccumAlphaBits = 0; pfd.DepthBits = 24; pfd.StencilBits = 8; pfd.AuxBuffers = 0; pfd.LayerType = 0; pfd.Reserved = 0; pfd.LayerMask = 0; pfd.VisibleMask = 0; pfd.DamageMask = 0; int pixelFormat; if ((pixelFormat = OpenGLInterops.ChoosePixelFormat(_deviceContext, ref pfd)) == 0) { throw new GraphicsException("Unable to choose pixel format."); } if (!OpenGLInterops.SetPixelFormat(_deviceContext, pixelFormat, ref pfd)) { throw new GraphicsException("Unable to set pixel format."); } _renderContext = OpenGLInterops.wglCreateContext(_deviceContext); OpenGLInterops.wglMakeCurrent(_deviceContext, _renderContext); try { int[] attributes = { (int)ContextAttributes.MajorVersion, 3, (int)ContextAttributes.MinorVersion, 3, (int)ContextAttributes.Flags, (int)ContextAttributes.ForwardCompatible, 0 }; var hrc = OpenGLInterops.CreateContextWithAttributes(_deviceContext, IntPtr.Zero, attributes); OpenGLInterops.wglMakeCurrent(IntPtr.Zero, IntPtr.Zero); OpenGLInterops.wglDeleteContext(_renderContext); OpenGLInterops.wglMakeCurrent(_deviceContext, hrc); _renderContext = hrc; } catch (MissingMethodException) { throw new GraphicsException("Unable to create OpenGL 3.3 context."); } }
/// <summary> /// Binds the current texture. /// </summary> internal void Bind() { OpenGLInterops.ActiveTexture(OpenGLInterops.GL_TEXTURE0); OpenGLInterops.BindTexture(OpenGLInterops.GL_TEXTURE_2D, Id); }
/// <summary> /// Unbinds the IndexBuffer. /// </summary> public void Unbind() { OpenGLInterops.BindBuffer(OpenGLInterops.GL_ELEMENT_ARRAY_BUFFER, 0); }
/// <summary> /// Sets the Data. /// </summary> /// <param name="vertices">The Vertices.</param> /// <remarks>Bind must be called in order to take effect.</remarks> public void SetData(float[] vertices) { OpenGLInterops.BufferData(OpenGLInterops.GL_ARRAY_BUFFER, vertices, OpenGLInterops.GL_STATIC_DRAW); }
/// <summary> /// Binds the VertexBuffer. /// </summary> public void Bind() { OpenGLInterops.BindBuffer(OpenGLInterops.GL_ARRAY_BUFFER, Id); }
/// <summary> /// Pushs the vertex attributes description. /// </summary> /// <param name="index">The Index.</param> /// <param name="size">The Size.</param> /// <param name="normalized">The normalized State.</param> /// <param name="stride">The Stride.</param> /// <param name="offset">The Offset.</param> public static void VertexAttribPointer(uint index, int size, bool normalized, int stride, int offset) { OpenGLInterops.VertexAttribPointer(index, size, OpenGLInterops.GL_FLOAT, normalized, stride, new IntPtr(offset)); }
/// <summary> /// Enables the vertex attribute array. /// </summary> /// <param name="index">The Index.</param> public static void EnableVertexAttribArray(uint index) { OpenGLInterops.EnableVertexAttribArray(index); }
/// <summary> /// Triggered if the screen size changed. /// </summary> /// <param name="sender">The Sender.</param> /// <param name="e">The EventArgs.</param> private void WindowScreenSizeChanged(object sender, EventArgs e) { _windowSize = _window.Size; OpenGLInterops.Viewport(0, 0, (int)_windowSize.X, (int)_windowSize.Y); }
/// <summary> /// Unbinds the VertexArray. /// </summary> public void Unbind() { OpenGLInterops.BindVertexArray(0); }
/// <summary> /// Clears the last opengl error. /// </summary> public static void ClearLastError() { OpenGLInterops.GetError(); }
/// <summary> /// Sets the Data. /// </summary> /// <param name="indices">The Indices.</param> /// <remarks>Bind must be called in order to take effect.</remarks> public void SetData(ushort[] indices) { OpenGLInterops.BufferData(OpenGLInterops.GL_ELEMENT_ARRAY_BUFFER, indices, OpenGLInterops.GL_STATIC_DRAW); }
/// <summary> /// Unbinds the texture. /// </summary> internal void Unbind() { OpenGLInterops.BindTexture(OpenGLInterops.GL_TEXTURE_2D, 0); }
/// <summary> /// Binds the VertexArray. /// </summary> public void Bind() { OpenGLInterops.BindVertexArray(Id); }
/// <summary> /// Gets the last error. /// </summary> /// <returns>OpenGLError.</returns> public static OpenGLError GetLastError() { return(OpenGLInterops.GetError()); }