/// <summary> /// Creates a framebuffer object and its associated resources (depth and pbuffers). /// </summary> /// <param name="Size">Specifies the size (in pixels) of the framebuffer and it's associated buffers.</param> /// <param name="Attachments">Specifies the attachments to use for the pbuffers.</param> /// <param name="Format">Specifies the internal pixel format for the pbuffers.</param> public FBO(Size Size, FramebufferAttachment[] Attachments, PixelInternalFormat Format, bool Mipmaps) { this.Size = Size; this.Attachments = Attachments; this.Format = Format; this.mipmaps = Mipmaps; // First create the framebuffer BufferID = Gl.GenFramebuffer(); Gl.BindFramebuffer(FramebufferTarget.Framebuffer, BufferID); if (Attachments.Length == 1 && Attachments[0] == FramebufferAttachment.DepthAttachment) { TextureID = new uint[] { Gl.GenTexture() }; Gl.BindTexture(TextureTarget.Texture2D, TextureID[0]); Gl.TexImage2D(TextureTarget.Texture2D, 0, Format, Size.Width, Size.Height, 0, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero); Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, TextureParameter.Nearest); Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, TextureParameter.Nearest); Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, TextureParameter.ClampToEdge); Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, TextureParameter.ClampToEdge); Gl.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, TextureID[0], 0); Gl.DrawBuffer(DrawBufferMode.None); Gl.ReadBuffer(ReadBufferMode.None); } else { // Create and attach a 24-bit depth buffer to the framebuffer DepthID = Gl.GenRenderbuffer(); Gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, DepthID); Gl.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent24, Size.Width, Size.Height); // Create n texture buffers (known by the number of attachments) TextureID = new uint[Attachments.Length]; Gl.GenTextures(Attachments.Length, TextureID); // Bind the n texture buffers to the framebuffer for (int i = 0; i < Attachments.Length; i++) { Gl.BindTexture(TextureTarget.Texture2D, TextureID[i]); Gl.TexImage2D(TextureTarget.Texture2D, 0, Format, Size.Width, Size.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero); if (Mipmaps) { Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, TextureParameter.Linear); Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, TextureParameter.LinearMipMapLinear); Gl.GenerateMipmap(GenerateMipmapTarget.Texture2D); } Gl.FramebufferTexture(FramebufferTarget.Framebuffer, Attachments[i], TextureID[i], 0); } // Build the framebuffer and check for errors Gl.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, DepthID); } FramebufferErrorCode status = Gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer); if (status != FramebufferErrorCode.FramebufferComplete) { Console.WriteLine("Frame buffer did not compile correctly. Returned {0}, glError: {1}", status.ToString(), Gl.GetError().ToString()); } Gl.BindFramebuffer(FramebufferTarget.Framebuffer, 0); }
/// <summary> /// Bind a named texture to a texturing target /// </summary> /// <param name="Texture">Specifies the texture.</param> public static void BindTexture(Texture Texture) { Gl.BindTexture(Texture.TextureTarget, Texture.TextureID); }
/// <summary> /// Create a texture from a supplie bitmap. /// </summary> /// <param name="BitmapImage">The already decoded bitmap image.</param> /// <param name="FlipY">True if the bitmap should be flipped.</param> public Texture(Bitmap BitmapImage, bool FlipY = true) { this.Filename = BitmapImage.GetHashCode().ToString(); LoadBitmap(BitmapImage, FlipY); Gl.BindTexture(TextureTarget, 0); }
/// <summary> /// Loads a compressed DDS file into an OpenGL texture. /// </summary> /// <param name="ResourceFile">The path to the DDS file.</param> private void LoadDDS(string ResourceFile) { using (BinaryReader stream = new BinaryReader(new FileStream(ResourceFile, FileMode.Open))) { string filecode = new string(stream.ReadChars(4)); if (filecode != "DDS ") // first 4 chars should be "DDS " { throw new Exception("File was not a DDS file format."); } DDS.DDSURFACEDESC2 imageData = new DDS.DDSURFACEDESC2(stream); // read the DirectDraw surface descriptor this.Size = new Size((int)imageData.Width, (int)imageData.Height); if (imageData.LinearSize == 0) { throw new Exception("The linear scan line size was zero."); } bool compressed = true; int factor = 0, buffersize = 0, blocksize = 0; PixelInternalFormat format; switch (imageData.PixelFormat.FourCC) // check the compression type { case "DXT1": // DXT1 compression ratio is 8:1 format = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext; factor = 2; blocksize = 8; break; case "DXT3": // DXT3 compression ratio is 4:1 format = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext; factor = 4; blocksize = 16; break; case "DXT5": // DXT5 compression ratio is 4:1 format = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext; factor = 4; blocksize = 16; break; default: compressed = false; if (imageData.PixelFormat.ABitMask == 0xf000 && imageData.PixelFormat.RBitMask == 0x0f00 && imageData.PixelFormat.GBitMask == 0x00f0 && imageData.PixelFormat.BBitMask == 0x000f && imageData.PixelFormat.RGBBitCount == 16) { format = PixelInternalFormat.Rgba; } throw new Exception(string.Format("File compression \"{0}\" is not supported.", imageData.PixelFormat.FourCC)); } if (imageData.LinearSize != 0) { buffersize = (int)((imageData.MipmapCount > 1) ? imageData.LinearSize * factor : imageData.LinearSize); } else { buffersize = (int)(stream.BaseStream.Length - stream.BaseStream.Position); } // read the pixel data and then pin it to memory so that the garbage collector // doesn't shuffle the data around while OpenGL is decompressing it byte[] pixels = stream.ReadBytes(buffersize); GCHandle pinned = GCHandle.Alloc(pixels, GCHandleType.Pinned); try { this.TextureTarget = (imageData.Height == 1 || imageData.Width == 1) ? TextureTarget.Texture1D : TextureTarget.Texture2D; this.TextureID = Gl.GenTexture(); Gl.BindTexture(TextureTarget, TextureID); Gl.TexParameteri(TextureTarget, TextureParameterName.TextureMinFilter, TextureParameter.Linear); Gl.TexParameteri(TextureTarget, TextureParameterName.TextureMagFilter, TextureParameter.Linear); int nOffset = 0, nWidth = (int)imageData.Width, nHeight = (int)imageData.Height; for (int i = 0; i < (imageData.MipmapCount == 0 ? 1 : imageData.MipmapCount); ++i) { if (nWidth == 0) { nWidth = 1; // smallest mipmap is 1x1 pixels } if (nHeight == 0) { nHeight = 1; } int nSize = 0; if (compressed) { nSize = ((nWidth + 3) / 4) * ((nHeight + 3) / 4) * blocksize; Gl.CompressedTexImage2D(TextureTarget, i, format, nWidth, nHeight, 0, nSize, (IntPtr)(pinned.AddrOfPinnedObject().ToInt64() + nOffset)); } else { nSize = nWidth * nHeight * 4 * ((int)imageData.PixelFormat.RGBBitCount / 8); Gl.TexImage2D(TextureTarget, i, format, nWidth, nHeight, 0, PixelFormat.Bgra, PixelType.UnsignedShort4444, (IntPtr)(pinned.AddrOfPinnedObject().ToInt64() + nOffset)); } nOffset += nSize; nWidth /= 2; nHeight /= 2; } } catch (Exception) { // There was some sort of Dll related error, or the target GPU does not support glCompressedTexImage2DARB throw; } finally { pinned.Free(); } } }
/// <summary> /// Unbind this Texture on specific target. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for binding this Texture. /// </param> /// <param name="target"> /// A <see cref="TextureTarget"/> that specify the texture target. /// </param> protected void Unbind(GraphicsContext ctx, TextureTarget target) { // Unbind this Texture on specified target Gl.BindTexture(target, 0); }
/// <summary> /// Bind this Texture on specific target. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for binding this Texture. /// </param> /// <param name="target"> /// A <see cref="TextureTarget"/> that specify the texture target. /// </param> protected void Bind(GraphicsContext ctx, TextureTarget target) { // Bind this Texture on specified target Gl.BindTexture(target, ObjectName); }