我正在制作具有一堆小窗口和控件的应用程序(所以它是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);
- ActivateRenderingContext(DC,RC);
- glClearColor(0.27,0.4,0.7,0.0);//Light blue
- glViewport(0,1280,1024);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity;
- glOrtho(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);
- glBegin(GL_QUADS);
- glVertex2f(100,100);
- glVertex2f(1280-100,1024-100);
- glVertex2f(100,1024-100);
- glend;
- //Output
- SwapBuffers(DC);
但是没有输出.
如果我使用MainForm.Canvas.Draw(0,BMP);然后会出现白色矩形.
我想在位图上渲染东西,因为我可以使用位图做很多事情(在它上面绘制图形,绘制文本,模糊),但如果有其他方法可以在屏幕外渲染,那么它没关系……
那么如何设置我的应用程序进行屏幕外渲染?
必须创建与目标设备上下文匹配的OpenGL上下文.对于Windows,它们的创建方式与位图不同.看到
http://msdn.microsoft.com/en-us/library/windows/desktop/dd368826(v=vs.85).aspx尤其是dwFlags,其中包括其他
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没有正确的语法着色,即找出评论的位置和不在哪里)
- // 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;
- }