private void LoadBitmap(Bitmap BitmapImage, bool FlipY = true) { /* .net library has methods for converting many image formats so I exploit that by using * .net to convert any filetype to a bitmap. Then the bitmap is locked into memory so * that the garbage collector doesn't touch it, and it is read via OpenGL glTexImage2D. */ if (FlipY) { BitmapImage.RotateFlip(RotateFlipType.RotateNoneFlipY); // bitmaps read from bottom up, so flip it } Size = BitmapImage.Size; // must be Format32bppArgb file format, so convert it if it isn't in that format BitmapData bitmapData = BitmapImage.LockBits(new Rectangle(0, 0, BitmapImage.Width, BitmapImage.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); // set the texture target and then generate the texture ID TextureTarget = TextureTarget.Texture2D; TextureID = GlUtility.GenTexture(); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); // set pixel alignment GL.BindTexture(TextureTarget, TextureID); // bind the texture to memory in OpenGL GL.TexImage2D(TextureTarget, 0, PixelInternalFormat.Rgba8, BitmapImage.Width, BitmapImage.Height, 0, PixelFormat.Bgra, PixelType.UnsignedByte, bitmapData.Scan0); GL.TexParameter(TextureTarget, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); BitmapImage.UnlockBits(bitmapData); BitmapImage.Dispose(); }
/// <summary> /// Creates a buffer object of type T. /// </summary> /// <param name="data">Specifies a pointer to data that will be copied into the data store for initialization.</param> /// <param name="target">Specifies the target buffer object.</param> /// <param name="hint">Specifies the expected usage of the data store.</param> public VBO(T[] data, BufferTarget target = BufferTarget.ArrayBuffer, BufferUsageHint hint = BufferUsageHint.StaticDraw) { vboID = GlUtility.CreateVBO <T>(BufferTarget = target, data, hint); Size = (data is int[] || data is float[] ? 1 : (data is Vector2[] ? 2 : (data is Vector3[] ? 3 : (data is Vector4[] ? 4 : 0)))); PointerType = (data is int[] ? VertexAttribPointerType.Int : VertexAttribPointerType.Float); Count = data.Length; }
/// <summary> /// Creates a buffer object of type T with a specified length. /// This allows the array T[] to be larger than the actual size necessary to buffer. /// Useful for reusing resources and avoiding unnecessary GC action. /// </summary> /// <param name="data">An array of data of type T (which must be a struct) that will be buffered to the GPU.</param> /// <param name="position"></param> /// <param name="length">The length of the valid data in the data array.</param> /// <param name="target">Specifies the target buffer object.</param> /// <param name="hint">Specifies the expected usage of the data store.</param> public VBO(T[] data, int position, int length, BufferTarget target = BufferTarget.ArrayBuffer, BufferUsageHint hint = BufferUsageHint.StaticDraw) { length = Math.Max(0, Math.Min(length, data.Length)); vboID = GlUtility.CreateVBO <T>(BufferTarget = target, data, hint, position, length); this.Size = (data is int[] || data is float[] ? 1 : (data is Vector2[] ? 2 : (data is Vector3[] ? 3 : (data is Vector4[] ? 4 : 0)))); this.PointerType = (data is int[] ? VertexAttribPointerType.Int : VertexAttribPointerType.Float); this.Count = length; }
public void Draw(Matrix4 fov, Matrix4 cameraView) { //Logging.Debug("Entering background draw."); if (!HasBackground) { return; } //Logging.Debug("We have a background."); _backgroundProgram.Use(); //Logging.Debug("Set background program."); GL.ActiveTexture(TextureUnit.Texture0); //Logging.Debug("Set active texture."); GlUtility.BindTexture(_backgroundTexture); //Logging.Debug("Bound background texture."); _backgroundProgram["projection_matrix"].SetValue(fov); _backgroundProgram["view_matrix"].SetValue(cameraView); //Logging.Debug("Bound background uniforms."); GlUtility.BindBuffer(_points); //Logging.Debug("Bound background points."); //vertexPosition GL.VertexAttribPointer(ShaderProgram.VertexPosition, 3, _points.PointerType, false, 5 * Marshal.SizeOf(typeof(float)), IntPtr.Zero); GL.EnableVertexAttribArray(ShaderProgram.VertexPosition); //Logging.Debug("Bound background positions to array."); GL.DisableVertexAttribArray(ShaderProgram.VertexColor); //Logging.Debug("Disabled VertexColor array."); GL.DisableVertexAttribArray(ShaderProgram.VertexSize); //textureCoords GL.VertexAttribPointer(ShaderProgram.TextureCoords, 2, _points.PointerType, false, 5 * Marshal.SizeOf(typeof(float)), Vector3.SizeInBytes); GL.EnableVertexAttribArray(ShaderProgram.TextureCoords); //Logging.Debug("Bound background texture coords to array."); GlUtility.BindBuffer(_backgroundElements); GL.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, IntPtr.Zero); //Logging.Debug("Exit background draw."); }
public void Draw(ShaderProgram program) { //Logging.Debug("Entering Draw."); if (_points.Count == 0) { //Logging.Debug("Exiting Draw."); return; } //program["pointSize"].SetValue((float)PixelSize); VBO <float> points = new VBO <float>(_points.ToArray()); //Logging.Debug("Created VBO."); GlUtility.BindBuffer(points); //Logging.Debug("Buffer Bound."); GL.VertexAttribPointer(ShaderProgram.VertexPosition, 3, VertexAttribPointerType.Float, false, EightFloatDataSize, IntPtr.Zero); GL.EnableVertexAttribArray(ShaderProgram.VertexPosition); //Logging.Debug("Point pointer set."); GL.VertexAttribPointer(ShaderProgram.VertexColor, 4, VertexAttribPointerType.Float, false, EightFloatDataSize, Vector3.SizeInBytes); GL.EnableVertexAttribArray(ShaderProgram.VertexColor); GL.VertexAttribPointer(ShaderProgram.VertexSize, 1, VertexAttribPointerType.Float, false, EightFloatDataSize, Vector3.SizeInBytes + Vector4.SizeInBytes); GL.EnableVertexAttribArray(ShaderProgram.VertexSize); GL.DisableVertexAttribArray(ShaderProgram.TextureCoords); //Logging.Debug("Color pointer set."); //Logging.Debug("Beginning draw."); // draw the points GL.DrawArrays(PrimitiveType.Points, 0, points.Count / 8); //Logging.Debug("Draw completed for shape."); points.Dispose(); //Logging.Debug("VBO Disposed."); //Logging.Debug("Exiting Draw."); }
/// <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 = DDS.DDSURFACEDESC2.FromBinaryReader(stream); //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; InternalFormat format; PixelInternalFormat pixelFormat; switch (imageData.PixelFormat.FourCC) // check the compression type { case "DXT1": // DXT1 compression ratio is 8:1 format = InternalFormat.CompressedRgbaS3tcDxt1Ext; pixelFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext; factor = 2; blocksize = 8; break; case "DXT3": // DXT3 compression ratio is 4:1 format = InternalFormat.CompressedRgbaS3tcDxt3Ext; pixelFormat = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext; factor = 4; blocksize = 16; break; case "DXT5": // DXT5 compression ratio is 4:1 format = InternalFormat.CompressedRgbaS3tcDxt5Ext; pixelFormat = 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 = InternalFormat.Rgba; pixelFormat = PixelInternalFormat.Rgba; } else if (imageData.PixelFormat.ABitMask == unchecked ((int)0xff000000) && imageData.PixelFormat.RBitMask == 0x00ff0000 && imageData.PixelFormat.GBitMask == 0x0000ff00 && imageData.PixelFormat.BBitMask == 0x000000ff && imageData.PixelFormat.RGBBitCount == 32) { format = InternalFormat.Rgba; pixelFormat = PixelInternalFormat.Rgba; } else { throw new Exception(string.Format("File compression \"{0}\" is not supported.", imageData.PixelFormat.FourCC)); } break; } 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 { TextureTarget = (imageData.Height == 1 || imageData.Width == 1) ? TextureTarget.Texture1D : TextureTarget.Texture2D; TextureID = GlUtility.GenTexture(); GL.BindTexture(TextureTarget, TextureID); GL.TexParameter(TextureTarget, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.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 { PixelType pixelType = imageData.PixelFormat.RGBBitCount == 16 ? PixelType.UnsignedShort4444Reversed : PixelType.UnsignedInt8888Reversed; nSize = nWidth * nHeight * imageData.PixelFormat.RGBBitCount / 8; GL.TexImage2D(TextureTarget, i, pixelFormat, nWidth, nHeight, 0, PixelFormat.Bgra, pixelType, (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(); } } }