Note that there are some explanatory texts on larger screens.

plurals
  1. POUnable to load most image formats as textures in OpenGL
    primarykey
    data
    text
    <p>I'm attempting to load a variety of image formats to display with alpha blending in OpenGL for our company's software, but I seem to have no luck on this. I'm trying to load Bitmaps like this:</p> <pre><code>private Bitmap LoadBitmap(string filename) { Bitmap original = new Bitmap(filename); Bitmap toReturn = new Bitmap(original.Width, original.Height, PixelFormat.Format24bppRgb); using (Graphics gr = Graphics.FromImage(toReturn)) { gr.DrawImage(original, new Rectangle(0, 0, toReturn.Width, toReturn.Height)); } original.Dispose(); return toReturn; } </code></pre> <p>Loading it into a texture like this:</p> <pre><code>private uint[] GetTexture(Bitmap convertToTexture) { // Setup return value uint[] toReturn = null; // Make sure the device and the bitmap exists if (convertToTexture != null) { // Dispose the imagery first DisposeTexture(); mImageryTexture = new uint[1]; // Setup the bitmap Rectangle rect = new Rectangle(Point.Empty, convertToTexture.Size); BitmapData bitmapdata = convertToTexture.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); // Bind the texture glGenTextures(1, mImageryTexture); glBindTexture(GL_TEXTURE_2D, mImageryTexture[0]); glTexImage2D(GL_TEXTURE_2D, 0, (int)GL_RGB8, convertToTexture.Width, convertToTexture.Height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, bitmapdata.Scan0); // Linear Filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Clamp glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // Release the bitmap convertToTexture.UnlockBits(bitmapdata); // Set the return value to this imagery toReturn = mImageryTexture; } return toReturn; } </code></pre> <p>And using the texture like this:</p> <pre><code>public bool DrawGLScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Test bitmap Rectangle rect = new Rectangle(); rect.Size = testBitmap.Size; RenderQuad(testBitmap, rect); RenderLines(rect); rect.X += rect.Width; // Test JPEG rect.Size = testJpeg.Size; RenderQuad(testJpeg, rect); RenderLines(rect); rect.X += rect.Width; // Test PNG rect.Size = testPng.Size; RenderQuad(testPng, rect); RenderLines(rect); rect.X += rect.Width; // Test GIF rect.Size = testGif.Size; RenderQuad(testGif, rect); RenderLines(rect); return true; } private void RenderQuad(Bitmap image, Rectangle rect) { uint[] imageryTexture = GetTexture(image); // Color all the vertices white with transparency glEnable(GL_TEXTURE_2D); glColor4ub(255, 255, 255, 255); /////////////////////////////////////////////////// // Draw the image of the area. /////////////////////////////////////////////////// // Fill the path with the background transparent color. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glBindTexture(GL_TEXTURE_2D, imageryTexture[0]); // Building a quad of the image glBegin(GL_QUADS); // top left of texture glTexCoord2f(0, 1); glVertex2i(rect.Left, rect.Top); // top right of texture glTexCoord2f(1, 1); glVertex2i(rect.Right, rect.Top); // bottom right of texture glTexCoord2f(1, 0); glVertex2i(rect.Right, rect.Bottom); // bottom left of texture glTexCoord2f(0, 0); glVertex2i(rect.Left, rect.Bottom); glEnd(); } private void RenderLines(Rectangle rect) { // Fill the path with the background transparent color. // Color all the vertices transparent gray Color LineColor = Color.Tomato; glColor4ub(LineColor.R, LineColor.G, LineColor.B, 255); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Building a quad of the image glBegin(GL_QUADS); // top left of texture glVertex2i(rect.Left, rect.Top); // top right of texture glVertex2i(rect.Right, rect.Top); // bottom right of texture glVertex2i(rect.Right, rect.Bottom); // bottom left of texture glVertex2i(rect.Left, rect.Bottom); glEnd(); } </code></pre> <p>What am I doing wrong? I can load some bitmap files, but not others. PNGs, JPEGs, and GIFs don't work at all. All I get are white squares (from the vertex colors).</p> <p>Here's the full code below. I'm using NeHe's lesson 2 code as basis for this code (since I can't post the company software code in its entirety):</p> <pre><code>public class OpenGLForm : Form { #region Member Variables private const string AbsolutePath = @"C:\&lt;path-to-images&gt;\"; /// &lt;summary&gt; /// Required designer variable. /// &lt;/summary&gt; private System.ComponentModel.Container components = null; private Bitmap testBitmap = null; private Bitmap testJpeg = null; private Bitmap testPng = null; private Bitmap testGif = null; private uint[] mImageryTexture = null; private static uint _hwnd = 0; private static uint _hDC = 0; private static uint _hRC = 0; private bool _appActive = true; private bool _done = true; public bool Done { get { return _done; } set { _done = value; } } #endregion // Lots of OpenGL function and constant declaration here #region Win32 Interop // Constant values were found in the "WinUser.h" header file. public const int WM_ACTIVATEAPP = 0x001C; public const int WA_ACTIVE = 1; public const int WA_CLICKACTIVE = 2; public const int CDS_FULLSCREEN = 0x00000004; // Flag for ChangeDisplaySettings public const int DISP_CHANGE_SUCCESSFUL = 0; // Return value for ChangeDisplaySettings // Constant values were found in the "WinGDI.h" header file. public const int CCHDEVICENAME = 32; // size of a device name string public const int CCHFORMNAME = 32; // size of a form name string public const int DM_BITSPERPEL = 0x40000; public const int DM_PELSWIDTH = 0x80000; public const int DM_PELSHEIGHT = 0x100000; public const int BITSPIXEL = 12; // number of bits per pixel public const uint PFD_DOUBLEBUFFER = 0x00000001; // PIXELFORMATDESCRIPTOR flag public const uint PFD_DRAW_TO_WINDOW = 0x00000004; // PIXELFORMATDESCRIPTOR flag public const uint PFD_SUPPORT_OPENGL = 0x00000020; // PIXELFORMATDESCRIPTOR flag public const uint PFD_TYPE_RGBA = 0; // pixel type public const uint PFD_MAIN_PLANE = 0; // layer type [StructLayout(LayoutKind.Sequential)] public struct PIXELFORMATDESCRIPTOR { public ushort nSize; public ushort nVersion; public uint dwFlags; public byte iPixelType; public byte cColorBits; public byte cRedBits; public byte cRedShift; public byte cGreenBits; public byte cGreenShift; public byte cBlueBits; public byte cBlueShift; public byte cAlphaBits; public byte cAlphaShift; public byte cAccumBits; public byte cAccumRedBits; public byte cAccumGreenBits; public byte cAccumBlueBits; public byte cAccumAlphaBits; public byte cDepthBits; public byte cStencilBits; public byte cAuxBuffers; public byte iLayerType; public byte bReserved; public uint dwLayerMask; public uint dwVisibleMask; public uint dwDamageMask; } // by marking the structure with CharSet.Auto, the structure will get marshaled as Unicode characters // on Unicode platforms, if not the name fields would always get marshaled as arrays of ANSI characters [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class DEVMODE { [MarshalAs(UnmanagedType.ByValArray, SizeConst = CCHDEVICENAME)] public char[] dmDeviceName; public short dmSpecVersion; public short dmDriverVersion; public short dmSize; public short dmDriverExtra; public int dmFields; public DEVMODE_UNION u; public short dmColor; public short dmDuplex; public short dmYResolution; public short dmTTOption; public short dmCollate; [MarshalAs(UnmanagedType.ByValArray, SizeConst = CCHFORMNAME)] public char[] dmFormName; public short dmLogPixels; public int dmBitsPerPel; public int dmPelsWidth; public int dmPelsHeight; public int dmDisplayFlagsOrdmNup; // union of dmDisplayFlags and dmNup public int dmDisplayFrequency; public int dmICMMethod; public int dmICMIntent; public int dmMediaType; public int dmDitherType; public int dmReserved1; public int dmReserved2; public int dmPanningWidth; public int dmPanningHeight; } // modeling a union in C#, each possible struct data type starts at FieldOffset 0 [StructLayout(LayoutKind.Explicit)] public struct DEVMODE_UNION { [FieldOffset(0)] public short dmOrientation; [FieldOffset(2)] public short dmPaperSize; [FieldOffset(4)] public short dmPaperLength; [FieldOffset(6)] public short dmPaperWidth; [FieldOffset(8)] public short dmScale; [FieldOffset(10)] public short dmCopies; [FieldOffset(12)] public short dmDefaultSource; [FieldOffset(14)] public short dmPrintQuality; [FieldOffset(0)] public int dmPosition_x; [FieldOffset(4)] public int dmPosition_y; [FieldOffset(0)] public int dmDisplayOrientation; [FieldOffset(0)] public int dmDisplayFixedOutput; } #endregion #region OpenGLSetup private bool SetupPixelFormat(ref uint hdc) { PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR(); ushort pfdSize = (ushort)Marshal.SizeOf(typeof(PIXELFORMATDESCRIPTOR)); // sizeof(PIXELFORMATDESCRIPTOR) pfd.nSize = pfdSize; // size of pfd pfd.nVersion = 1; // version number pfd.dwFlags = (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER); // flags pfd.iPixelType = (byte)PFD_TYPE_RGBA; // RGBA type pfd.cColorBits = (byte)GetDeviceCaps(hdc, BITSPIXEL); // color depth pfd.cRedBits = 0; // color bits ignored pfd.cRedShift = 0; pfd.cGreenBits = 0; pfd.cGreenShift = 0; pfd.cBlueBits = 0; pfd.cBlueShift = 0; pfd.cAlphaBits = 0; // no alpha buffer pfd.cAlphaShift = 0; // shift bit ignored pfd.cAccumBits = 0; // no accumulation buffer pfd.cAccumRedBits = 0; // accum bits ignored pfd.cAccumGreenBits = 0; pfd.cAccumBlueBits = 0; pfd.cAccumAlphaBits = 0; pfd.cDepthBits = 32; // 32-bit z-buffer pfd.cStencilBits = 0; // no stencil buffer pfd.cAuxBuffers = 0; // no auxiliary buffer pfd.iLayerType = (byte)PFD_MAIN_PLANE; // main layer pfd.bReserved = 0; // reserved pfd.dwLayerMask = 0; // layer masks ignored pfd.dwVisibleMask = 0; pfd.dwDamageMask = 0; int pixelformat = ChoosePixelFormat(hdc, ref pfd); if (pixelformat == 0) // Did Windows Find A Matching Pixel Format? { MessageBox.Show("Can't Find A Suitable PixelFormat.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } if (SetPixelFormat(hdc, pixelformat, ref pfd) == 0) // Are We Able To Set The Pixel Format? { MessageBox.Show("Can't Set The PixelFormat.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } return true; } private bool InitGL() // All Setup For OpenGL Goes Here { glShadeModel(GL_SMOOTH); // Enable Smooth Shading glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background glClearDepth(1.0f); // Depth Buffer Setup // Add alpha blending support glDepthFunc(GL_LEQUAL); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); return true; // Initialization Went OK } public bool SetupRenderingContext() { if (!CreateGLWindow()) { return false; // initialization failed, quit } _hwnd = (uint)((this.Handle).ToInt32()); _hDC = GetDC(_hwnd); if (_hDC == 0) { MessageBox.Show("Can't Create A GL Device Context", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } // not doing the following wglSwapBuffers() on the DC will result in a failure to subsequently create the RC wglSwapBuffers(_hDC); if (!SetupPixelFormat(ref _hDC)) { return false; } // create the rendering context and make it current _hRC = wglCreateContext(_hDC); if (_hRC == 0) // Are We Able To Get A Rendering Context? { MessageBox.Show("Can't Create A GL Rendering Context.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } if (!wglMakeCurrent(_hDC, _hRC)) // Try To Activate The Rendering Context { MessageBox.Show("Can't Activate The GL Rendering Context.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } OpenGLForm_Resize(this, new EventArgs()); // Set up the perspective GL screen return InitGL(); // Initialize Our Newly Created GL Window } #endregion #region FormSetup private bool CreateGLWindow() { Resize += new EventHandler(OpenGLForm_Resize); TopMost = false; WindowState = System.Windows.Forms.FormWindowState.Normal; FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable; // The cursor is displayed only if the display count is greater than or equal to 0 do { }while (ShowCursor(true) &lt; 0); return true; } #endregion #region Constructor/Destructor public OpenGLForm() { // // Required for Windows Form Designer support // InitializeComponent(); testBitmap = LoadBitmap(AbsolutePath + "bitmap.bmp"); testJpeg = LoadBitmap(AbsolutePath + "jpeg.jpg"); testPng = LoadBitmap(AbsolutePath + "png.png"); testGif = LoadBitmap(AbsolutePath + "gif.gif"); } /// &lt;summary&gt; /// Clean up any resources being used. /// &lt;/summary&gt; protected override void Dispose(bool disposing) { if (disposing) { if (components != null) { components.Dispose(); } if (_hRC != 0) // Do We Have A Rendering Context? { if (!wglMakeCurrent(0, 0)) // Are We Able To Release The DC And RC Contexts? { MessageBox.Show("Release Of DC And RC Failed.", "Shutdown Error", MessageBoxButtons.OK, MessageBoxIcon.Information); } if (!wglDeleteContext(_hRC)) // Are We Able To Delete The RC? { MessageBox.Show("Release Rendering Context Failed.", "Shutdown Error", MessageBoxButtons.OK, MessageBoxIcon.Information); } } if (_hDC != 0 &amp;&amp; ReleaseDC(_hwnd, _hDC) == 0) // Are We Able To Release The DC { MessageBox.Show("Release Device Context Failed.", "Shutdown Error", MessageBoxButtons.OK, MessageBoxIcon.Information); } } base.Dispose(disposing); } private Bitmap LoadBitmap(string filename) { Bitmap original = new Bitmap(filename); Bitmap toReturn = new Bitmap(original.Width, original.Height, PixelFormat.Format24bppRgb); using (Graphics gr = Graphics.FromImage(toReturn)) { gr.DrawImage(original, new Rectangle(0, 0, toReturn.Width, toReturn.Height)); } original.Dispose(); return toReturn; } #endregion #region Windows Form Designer generated code /// &lt;summary&gt; /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// &lt;/summary&gt; private void InitializeComponent() { // // OpenGLForm // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(632, 453); this.KeyPreview = true; this.Name = "OpenGLForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "\"NeHe\'s First Polygon Tutorial\""; this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.OpenGLForm_KeyUp); } #endregion #region Events protected override void WndProc(ref System.Windows.Forms.Message m) { // Listen for operating system messages. switch (m.Msg) { // The WM_ACTIVATEAPP message occurs when the application // becomes the active application or becomes inactive. case WM_ACTIVATEAPP: { // The WParam value identifies what is occurring. _appActive = ((int)m.WParam == WA_ACTIVE || (int)m.WParam == WA_CLICKACTIVE); // Invalidate to get new scene painted. Invalidate(); break; } default: { break; } } base.WndProc(ref m); } /*! This will stop the display from flickering on Paint event */ protected override void OnPaintBackground(PaintEventArgs e) { } protected override void OnPaint(PaintEventArgs e) { // make sure the app is active if (_appActive) { DrawGLScene(); wglSwapBuffers(_hDC); Invalidate(); } } private void OpenGLForm_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) { switch (e.KeyCode) { case Keys.Escape: { Close(); break; } default: { break; } } } private void OpenGLForm_Resize(object sender, EventArgs e) // Resize And Initialize The GL Window { int width = ClientRectangle.Width; int height = ClientRectangle.Height; if (height == 0) // Prevent A Divide By Zero By { height = 1; // Making Height Equal One } // Switch to projection mode glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Change to ortho-graphic camera, with top left as (0, 0) coordinate, // and bottom right as the control size gluOrtho2D(0, ClientRectangle.Width, ClientRectangle.Height, 0); glViewport(0, 0, ClientRectangle.Width, ClientRectangle.Height); // Switch back to model view glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Reset The Modelview Matrix } #endregion /// &lt;summary&gt; /// The main entry point for the application. /// &lt;/summary&gt; [STAThread] static void Main() { while (true) { OpenGLForm form = new OpenGLForm(); // create the form if (!form.SetupRenderingContext()) // setup form and OpenGL { break; // initialization failed, quit } Application.Run(form); if (form.Done) // Was There A Quit Received? { form.DisposeTexture(); break; } } } public bool DrawGLScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Test bitmap Rectangle rect = new Rectangle(); rect.Size = testBitmap.Size; RenderQuad(testBitmap, rect); RenderLines(rect); rect.X += rect.Width; // Test JPEG rect.Size = testJpeg.Size; RenderQuad(testJpeg, rect); RenderLines(rect); rect.X += rect.Width; // Test PNG rect.Size = testPng.Size; RenderQuad(testPng, rect); RenderLines(rect); rect.X += rect.Width; // Test GIF rect.Size = testGif.Size; RenderQuad(testGif, rect); RenderLines(rect); return true; } private void RenderQuad(Bitmap image, Rectangle rect) { uint[] imageryTexture = GetTexture(image); // Color all the vertices white with transparency glEnable(GL_TEXTURE_2D); glColor4ub(255, 255, 255, 255); /////////////////////////////////////////////////// // Draw the image of the area. /////////////////////////////////////////////////// // Fill the path with the background transparent color. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glBindTexture(GL_TEXTURE_2D, imageryTexture[0]); // Building a quad of the image glBegin(GL_QUADS); // top left of texture glTexCoord2f(0, 1); glVertex2i(rect.Left, rect.Top); // top right of texture glTexCoord2f(1, 1); glVertex2i(rect.Right, rect.Top); // bottom right of texture glTexCoord2f(1, 0); glVertex2i(rect.Right, rect.Bottom); // bottom left of texture glTexCoord2f(0, 0); glVertex2i(rect.Left, rect.Bottom); glEnd(); } private void RenderLines(Rectangle rect) { // Fill the path with the background transparent color. // Color all the vertices transparent gray Color LineColor = Color.Tomato; glColor4ub(LineColor.R, LineColor.G, LineColor.B, 255); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Building a quad of the image glBegin(GL_QUADS); // top left of texture glVertex2i(rect.Left, rect.Top); // top right of texture glVertex2i(rect.Right, rect.Top); // bottom right of texture glVertex2i(rect.Right, rect.Bottom); // bottom left of texture glVertex2i(rect.Left, rect.Bottom); glEnd(); } // Creates a texture from a given bitmap. private uint[] GetTexture(Bitmap convertToTexture) { // Setup return value uint[] toReturn = null; // Make sure the device and the bitmap exists if (convertToTexture != null) { // Dispose the imagery first DisposeTexture(); mImageryTexture = new uint[1]; // Setup the bitmap Rectangle rect = new Rectangle(Point.Empty, convertToTexture.Size); BitmapData bitmapdata = convertToTexture.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); // Bind the texture glGenTextures(1, mImageryTexture); glBindTexture(GL_TEXTURE_2D, mImageryTexture[0]); glTexImage2D(GL_TEXTURE_2D, 0, (int)GL_RGB8, convertToTexture.Width, convertToTexture.Height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, bitmapdata.Scan0); // Linear Filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Clamp glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // Release the bitmap convertToTexture.UnlockBits(bitmapdata); // Set the return value to this imagery toReturn = mImageryTexture; } return toReturn; } // Disposes the currently held texture. public void DisposeTexture() { if (mImageryTexture != null) { glDeleteTextures(1, mImageryTexture); mImageryTexture = null; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload