OpenGL – 直接渲染到位图

我正在制作的应用程序中有一些小窗口和控件(所以它是2D渲染),我想呈现每个窗口和控制到自己的位图(有没有这么多)。 这是什么:

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; 

渲染程序:

  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; //Output SwapBuffers(DC); 

但是没有产出。
如果我使用MainForm.Canvas.Draw(0, 0, BMP); 那么会出现白色矩形。

我想在位图上进行渲染,因为我可以在位图上绘制很多graphics(绘制graphics,绘制文本,模糊),但是如果还有其他方法可以执行离屏渲染,那么就可以了。

那么如何设置我的屏幕外渲染应用程序呢?

必须创建与目标设备上下文匹配的OpenGL上下文。 对于窗口,它们以与位图不同的方式创建。 请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/dd368826(v=vs.85).aspx值得注意的是dwFlags ,其中还有其他

PFD_DRAW_TO_WINDOW缓冲区可以绘制到窗口或设备表面。

PFD_DRAW_TO_BITMAP缓冲区可以绘制到内存位图。

但是,你不应该超前,并为你的DIB DC创建一个渲染上下文。 为什么? 由于OpenGL渲染DIB部分的上下文将使用只支持CPU上运行的OpenGL-1.1的软件光栅化程序,因此速度会很慢。

相反,你应该创建一个Framebuffer对象,附加一个颜色渲染缓冲附件,并完成后,一个glReadPixels到你的DIBSection。 更容易,更快。

由于评论请求而更新

(我不知道为什么StackOverflow没有得到正确的语法着色,即找出评论和哪里不是)

 // 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; }