windows – OpenGL – 直接渲染到位图

前端之家收集整理的这篇文章主要介绍了windows – OpenGL – 直接渲染到位图前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在制作具有一堆小窗口和控件的应用程序(所以它是2D渲染),我想将每个窗口和控件渲染到它自己的位图(没有那么多).这有:
  1. uses dglOpenGL;
  2. ...
  3. var BMP: TBitmap;
  4. DC,RC: HDC;
  5. ...
  6. function TMainForm.Init: Boolean;
  7. begin
  8. Result := InitOpenGL;
  9. if Result = True then
  10. begin
  11. BMP := TBitmap.Create;
  12. BMP.PixelFormat := pf24bit;
  13. BMP.Width := 1280;
  14. BMP.Height := 1024;
  15.  
  16. DC := (BMP.Canvas.Handle);
  17. RC := CreateRenderingContext(DC,[opGDI,opDoubleBuffered],//tried changing,didn't help
  18. 24,24,0);
  19. ActivateRenderingContext(DC,RC);
  20.  
  21. glClearColor(0.27,0.4,0.7,0.0);//Light blue
  22. glViewport(0,1280,1024);
  23. glMatrixMode(GL_PROJECTION);
  24. glLoadIdentity;
  25. glOrtho(0,1024,-1,10);
  26. glMatrixMode(GL_MODELVIEW);
  27. glLoadIdentity;
  28. end;
  29. end;

渲染程序:

  1. glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  2. //Red quad
  3. glColor3f(1,0);
  4. glBegin(GL_QUADS);
  5. glVertex2f(100,100);
  6. glVertex2f(1280-100,1024-100);
  7. glVertex2f(100,1024-100);
  8. glend;
  9.  
  10. //Output
  11. SwapBuffers(DC);

但是没有输出.
如果我使用MainForm.Canvas.Draw(0,BMP);然后会出现白色矩形.

我想在位图上渲染东西,因为我可以使用位图做很多事情(在它上面绘制图形,绘制文本,模糊),但如果有其他方法可以在屏幕外渲染,那么它没关系……

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

必须创建与目标设备上下文匹配的OpenGL上下文.对于Windows,它们的创建方式与位图不同.看到
http://msdn.microsoft.com/en-us/library/windows/desktop/dd368826(v=vs.85).aspx尤其是dwFlags,其中包括其他

PFD_DRAW_TO_WINDOW The buffer can draw to a window or device surface.

PFD_DRAW_TO_BITMAP The buffer can draw to a memory bitmap.

但是,您不应该抢先为DIB DC创建渲染上下文.为什么?因为它会很慢,因为在DIB部分上的OpenGL渲染上下文将使用仅支持cpu上运行的OpenGL-1.1的软件光栅化器.

相反,您应该创建一个Framebuffer对象,附加一个颜色渲染缓冲附件,并在完成glReadPixels时进入您的DIBSection.更容易,更快.

由于评论请求而更新

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

  1. // flushes the OpenGL error queue and
  2. // counts the total number of errors
  3. int flushGLErrors(void)
  4. {
  5. int i = 0;
  6. while( glGetError() != GL_NO_ERROR ) {
  7. i++;
  8. }
  9.  
  10. return i;
  11. }
  12.  
  13. // returns a HBITMAP or NULL.
  14. // The HBITMAP must be freed using DeleteObject
  15. HBITMAP ReadPixelsToHBITMAP(
  16. int x,int y,int width,int height )
  17. {
  18. void *pdata = NULL;
  19.  
  20. /* Note that this values only makes sense if we know a target
  21. * output size like if we put the image to paper. */
  22. const int physical_resolution = 2835; /* 72 DPI */
  23.  
  24. BITMAPINFOHEADER bmih = {
  25. /* .biSize = */ sizeof(bmih),/* .biWidth = */ width,/* .bi.Height = */ height,/* .biPlanes = */ 1,/* mandatory */
  26. /* .biBitCount = */ 24,/* 8 bits per pixel */
  27. /* .biCompression = */ BI_RGB,/* uncompressed */
  28. /* .biSizeImage = */ 0,/* implicit */
  29. /* .biXPelsPerMeter = */ physical_resolution,/* ignored */
  30. /* .biYPelsPerMeter = */ physical_resolution,/* ignored */
  31. /* .biClrUsed = */ 0,/* no palette */
  32. /* .biClrImportant = */ 0
  33. };
  34.  
  35. HBITMAP hbm = CreateDIBSection(
  36. hdc,/* may be different than the DC used for OpenGL */
  37. (PBITMAPINFO)&bmih,/* can do this cast,because no palette is used */
  38. DIB_RGB_COLORS,&pdata,NULL,0
  39. );
  40.  
  41. if( !hbm ) {
  42. return NULL;
  43. }
  44.  
  45. flushGLErrors();
  46.  
  47. glPixelStorei(GL_PACK_SWAP_BYTES,GL_FALSE);
  48. glPixelStorei(GL_PACK_LSB_FIRST,GL_TRUE);
  49. glPixelStorei(GL_PACK_ROW_LENGTH,0);
  50. glPixelStorei(GL_PACK_IMAGE_HEIGHT,0);
  51. glPixelStorei(GL_PACK_SKIP_PIXELS,0);
  52. glPixelStorei(GL_PACK_SKIP_ROWS,0);
  53. glPixelStorei(GL_PACK_ALIGNMENT,1);
  54.  
  55. if( glGetError() != GL_NO_ERROR ) {
  56. DeleteObject(hbm);
  57. return NULL;
  58. }
  59.  
  60. glReadPixels(x,y,width,height,GL_BGR,GL_UNSIGNED_BYTE,pdata);
  61.  
  62. if( glGetError() != GL_NO_ERROR ) {
  63. DeleteObject(hbm);
  64. return NULL;
  65. }
  66.  
  67. return hbm;
  68. }

猜你在找的Windows相关文章