/// <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) { Filename = BitmapImage.GetHashCode().ToString(); LoadBitmap(BitmapImage, FlipY); Gl.BindTexture(TextureTarget, 0); }
/// <summary> /// Performs the draw routine with a custom shader program. /// </summary> /// <param name="program"></param> public void DrawProgram(ShaderProgram program) { BindAttributes(program); Gl.DrawElements(DrawMode, VertexCount, DrawElementsType.UnsignedInt, IntPtr.Zero); }
/// <summary> /// Binds a VBO based on the buffer target. /// </summary> /// <param name="buffer">The VBO to bind.</param> public static void BindBuffer <T>(VBO <T> buffer) where T : struct { Gl.BindBuffer(buffer.BufferTarget, buffer.vboID); }
/// <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; 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; } 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 = 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 = 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 { PixelType pixelType = imageData.PixelFormat.RGBBitCount == 16 ? PixelType.UnsignedShort4444Reversed : PixelType.UnsignedInt8888Reversed; nSize = nWidth * nHeight * imageData.PixelFormat.RGBBitCount / 8; Gl.TexImage2D(TextureTarget, i, format, nWidth, nHeight, 0, PixelFormat.Bgra, pixelType, (IntPtr)(pinned.AddrOfPinnedObject().ToInt64() + nOffset)); } nOffset += nSize; nWidth /= 2; nHeight /= 2; } #if MEMORY_LOGGER MemoryLogger.AllocateTexture(TextureID, Size); #endif } catch (Exception) { // There was some sort of Dll related error, or the target GPU does not support glCompressedTexImage2DARB throw; } finally { pinned.Free(); } } }
/// <summary> /// Installs a program object as part of current rendering state. /// </summary> /// <param name="Program">Specifies the handle of the program object whose executables are to be used as part of current rendering state.</param> public static void UseProgram(ShaderProgram Program) { Gl.UseProgram(Program.ProgramID); }
/// <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> /// Shortcut for quickly generating a single renderbuffer object without creating an array /// to pass to the gl function. Calls Gl.GenRenderbuffers(1, id). /// </summary> /// <returns>The ID of the generated framebuffer. 0 on failure.</returns> public static uint GenRenderbuffer() { uint1[0] = 0; Gl.GenRenderbuffers(1, uint1); return(uint1[0]); }
/// <summary> /// Shortcut for quickly generating a single framebuffer object without creating an array /// to pass to the gl function. Calls Gl.GenFramebuffers(1, id). /// </summary> /// <returns>The ID of the generated framebuffer. 0 on failure.</returns> public static uint GenFramebuffer() { Gl.GenFramebuffers(1, uint1); return(uint1[0]); }
/// <summary> /// Shortcut for quickly generating a single vertex array id without creating an array to /// pass to the gl function. Calls Gl.GenVertexArrays(1, id). /// </summary> /// <returns>The ID of the generated vertex array. 0 on failure.</returns> public static uint GenVertexArray() { uint1[0] = 0; Gl.GenVertexArrays(1, uint1); return(uint1[0]); }
/// <summary> /// Shortcut for quickly generating a single texture id without creating an array to /// pass to the gl function. Calls Gl.GenTexture(1, id). /// </summary> /// <returns>The ID of the generated texture. 0 on failure.</returns> public static uint GenTexture() { uint1[0] = 0; Gl.GenTextures(1, uint1); return(uint1[0]); }
/// <summary> /// Query the OpenGL implementation limits. /// </summary> /// <param name="glExtensions"> /// A <see cref="Gl.Extensions"/> that specify the supported OpenGL extension by the current /// implementation. /// </param> /// <returns> /// It returns a <see cref="GraphicsLimits"/> that specify the current OpenGL implementation limits. /// </returns> /// <remarks> /// It is assumed to have a valid OpenGL context current on the calling thread. /// </remarks> public static GraphicsLimits Query(Gl.Extensions glExtensions) { if (glExtensions == null) throw new ArgumentNullException("glExtensions"); KhronosApi.LogComment("Query OpenGL implementation imits."); GraphicsLimits graphicsLimits = new GraphicsLimits(); FieldInfo[] graphicsLimitsFields = typeof(GraphicsLimits).GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo field in graphicsLimitsFields) { GraphicsLimitAttribute graphicsLimitAttribute = (GraphicsLimitAttribute)Attribute.GetCustomAttribute(field, typeof(GraphicsLimitAttribute)); Attribute[] graphicsExtensionAttributes = Attribute.GetCustomAttributes(field, typeof(KhronosApi.ExtensionAttribute)); MethodInfo getMethod; if (graphicsLimitAttribute == null) continue; // Check extension support if ((graphicsExtensionAttributes != null) && (graphicsExtensionAttributes.Length > 0)) { bool supported = Array.Exists(graphicsExtensionAttributes, delegate(Attribute item) { return glExtensions.HasExtensions(((KhronosApi.ExtensionAttribute)item).ExtensionName); }); if (supported == false) continue; } // Determine which method is used to get the OpenGL limit if (field.FieldType != typeof(String)) { if (field.FieldType.IsArray == true) getMethod = typeof(Gl).GetMethod("Get", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Int32), field.FieldType }, null); else getMethod = typeof(Gl).GetMethod("Get", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Int32), field.FieldType.MakeByRefType() }, null); } else getMethod = typeof(Gl).GetMethod("GetString", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Int32) }, null); if (getMethod != null) { if (field.FieldType != typeof(String)) { object obj; if (field.FieldType.IsArray == false) obj = Activator.CreateInstance(field.FieldType); else obj = Array.CreateInstance(field.FieldType.GetElementType(), graphicsLimitAttribute.ArrayLenght); object[] @params = new object[] { graphicsLimitAttribute.EnumValue, obj }; try { getMethod.Invoke(null, @params); field.SetValue(graphicsLimits, @params[1]); } catch (Exception) { } } else { try { string s = (string)getMethod.Invoke(null, new object[] { graphicsLimitAttribute.EnumValue }); field.SetValue(graphicsLimits, s); } catch (Exception) { } } } else throw new InvalidOperationException("GraphicsLimits field " + field.Name + " doesn't have a OpenGL compatible type"); string fieldValueString; object fieldValue = field.GetValue(graphicsLimits); if (fieldValue is Array) { StringBuilder sb = new StringBuilder(); sb.Append("{ "); if (((Array)fieldValue).Length > 0) { foreach (object arrayItem in (Array)fieldValue) sb.AppendFormat("{0}, ", arrayItem); sb.Remove(sb.Length - 2, 2); } sb.Append(" }"); fieldValueString = sb.ToString(); } else fieldValueString = fieldValue.ToString(); } return (graphicsLimits); }