OpenGL - display directly in a raster image

I am making an application that has several small windows and controls (2D rendering), and I would like to display each window and control in its own bitmap. This is what is still there:

uses dglOpenGL; ... var BMP: TBitmap; DC, RC: HDC; ... function TMainForm.Init: Boolean; begin Result := InitOpenGL; if Result = True then begin BMP := TBitmap.Create; BMP.PixelFormat := pf24bit; BMP.Width := 1280; BMP.Height := 1024; DC := (BMP.Canvas.Handle); RC := CreateRenderingContext(DC, [opGDI, opDoubleBuffered], // tried changing, didn't help 24, 24, 0, 0, 0, 0); ActivateRenderingContext(DC, RC); glClearColor(0.27, 0.4, 0.7, 0.0); // light blue glViewport(0, 0, 1280, 1024); glMatrixMode(GL_PROJECTION); glLoadIdentity; glOrtho(0, 1280, 0, 1024, -1, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity; end; end; 

Rendering Procedure:

  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); // red quad glColor3f(1, 0, 0); glBegin(GL_QUADS); glVertex2f(100, 100); glVertex2f(1280-100, 100); glVertex2f(1280-100, 1024-100); glVertex2f(100, 1024-100); glend; // swap SwapBuffers(DC); 

But there is no way out.
If I use MainForm.Canvas.Draw(0, 0, BMP); then a white rectangle will appear.

I want to do rendering on bitmaps, because I can do a lot with bitmaps (draw other images, draw text, blur), but if there is another way to do offscreen rendering, then everything is fine ...

So how do I set up an app for off-screen rendering?

+6
source share
1 answer

OpenGL contexts must be created according to the context of the target device. For windows, they are created differently than for raster images. See http://msdn.microsoft.com/en-us/library/windows/desktop/dd368826(v=vs.85).aspx , in particular dwFlags , where there are among others

PFD_DRAW_TO_WINDOW The buffer can draw on the surface of a window or device.

PFD_DRAW_TO_BITMAP The buffer can draw into a memory bitmap.

However, you must rush ahead and create a visualization context for your DC DIB. What for? Since it will be slow, since the OpenGL rendering features in the DIB section will use a software rasterizer that only supports OpenGL-1.1 running on the CPU.

Instead, you should create a Framebuffer Object, attach a renderbuffer color application to it, and do away with glReadPixels in the DIBSection. Much easier, much faster.

Update due to request for comments

(I have no idea why StackOverflow doesn't get the correct syntax coloring, i.e. figure out where the comment is and where not)

 // flushes the OpenGL error queue and // counts the total number of errors int flushGLErrors(void) { int i = 0; while( glGetError() != GL_NO_ERROR ) { i++; } return i; } // returns a HBITMAP or NULL. // The HBITMAP must be freed using DeleteObject HBITMAP ReadPixelsToHBITMAP( int x, int y, int width, int height ) { void *pdata = NULL; /* Note that this values only makes sense if we know a target * output size like if we put the image to paper. */ const int physical_resolution = 2835; /* 72 DPI */ BITMAPINFOHEADER bmih = { /* .biSize = */ sizeof(bmih), /* .biWidth = */ width, /* .bi.Height = */ height, /* .biPlanes = */ 1, /* mandatory */ /* .biBitCount = */ 24, /* 8 bits per pixel */ /* .biCompression = */ BI_RGB, /* uncompressed */ /* .biSizeImage = */ 0, /* implicit */ /* .biXPelsPerMeter = */ physical_resolution, /* ignored */ /* .biYPelsPerMeter = */ physical_resolution, /* ignored */ /* .biClrUsed = */ 0, /* no palette */ /* .biClrImportant = */ 0 }; HBITMAP hbm = CreateDIBSection( hdc, /* may be different than the DC used for OpenGL */ (PBITMAPINFO)&bmih, /* can do this cast, because no palette is used */ DIB_RGB_COLORS, &pdata, NULL, 0 ); if( !hbm ) { return NULL; } flushGLErrors(); glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE); glPixelStorei(GL_PACK_LSB_FIRST, GL_TRUE); glPixelStorei(GL_PACK_ROW_LENGTH, 0); glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glPixelStorei(GL_PACK_ALIGNMENT, 1); if( glGetError() != GL_NO_ERROR ) { DeleteObject(hbm); return NULL; } glReadPixels(x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, pdata); if( glGetError() != GL_NO_ERROR ) { DeleteObject(hbm); return NULL; } return hbm; } 
+10
source

All Articles