хорошо, если вы хотите OpenGL вам нужен период окна.Но окно не обязательно должно быть видно на экране.Вы можете комбинировать GDI и OpenGL вместе, чтобы достичь своей цели.
Отрисовывать материал с экрана в растровое изображение с помощью OpenGL
с использованием невидимого окна с тем же разрешением, что и на рабочем столе.Если окно невидимо, оно не будет реагировать на события мыши или клавиатуры ...
Копировать изображение GL в память на стороне процессора
simple glReadPixels
будет делать.
Скопировать изображение на рабочий стол (используя растровое изображение GDI)
просто преобразовать / скопировать необработанные данные изображения в GDI-совместимыйрастровое изображение, а затем просто нарисуйте его на рабочий стол холста.Поэтому больше нет SwapBuffers(hdc);
, как в стандартном приложении GL.
Я кодирую в среде C ++ / VCL , поэтому у меня нет чистого WinAPI / GDI knwoledge (VCL делает это для меня, но код должен быть очень похожим, передаваемые имена и операнды могут немного отличаться, но не слишком сильно).
Это то, с чем я прихожу:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <gl\gl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1; // VCL Application window object
TCanvas *scr=NULL; // Desktop
DWORD *txr=NULL; // memory for GPU->CPU image transfer
Graphics::TBitmap *bmp=NULL; // bitmap for CPU->Desktop image transfer
int xs,ys; // desktop resolution
HDC hdc=NULL; // device context for GL
HGLRC hrc=NULL; // rendering context for GL
//---------------------------------------------------------------------------
void gl_draw()
{
if (scr==NULL) return;
if (bmp==NULL) return;
if (txr==NULL) return;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
// desktop pixel units
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranslatef(-1.0,+1.0,0.0);
glScalef(2.0/float(xs),-2.0/float(ys),1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// render rectangle
GLfloat fx=xs/2,fy=ys/2,fz=0.0,fa=(xs/2)-10,fb=(ys/2)-10;
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE_LOOP);
glVertex3f(fx-fa,fy-fb,fz);
glVertex3f(fx-fa,fy+fb,fz);
glVertex3f(fx+fa,fy+fb,fz);
glVertex3f(fx+fa,fy-fb,fz);
glEnd();
if (Form1->Visible) // normal window GL render
{
glFlush();
SwapBuffers(hdc);
}
else{ // copy GL image directly to desktop
// copy GL image to CPU side memory
glFlush();
glReadPixels(0,0,xs,ys,GL_RGBA,GL_UNSIGNED_BYTE,txr);
// copy it to bitmap
int x,y,a; DWORD *p;
for (a=0,y=0;y<ys;y++)
for (p=(DWORD*)bmp->ScanLine[y],x=0;x<xs;x++,a++)
p[x]=txr[a];
// render it to desktop
scr->Draw(0,0,bmp);
}
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
// desktop
scr=new TCanvas();
scr->Handle=GetDC(NULL);
xs=scr->ClipRect.Width();
ys=scr->ClipRect.Height()-31; // leave taskbar out of it
// BMP
bmp=new Graphics::TBitmap;
bmp->HandleType=bmDIB;
bmp->PixelFormat=pf32bit;
bmp->SetSize(xs,ys);
// txr buffer
txr=new DWORD[xs*ys];
// window
BorderStyle=bsNone;
SetBounds(0,0,xs,ys);
// GL init
hdc = GetDC(Handle); // get device context for this App window
PIXELFORMATDESCRIPTOR pfd;
ZeroMemory( &pfd, sizeof( pfd ) ); // set the pixel format for the DC
pfd.nSize = sizeof( pfd );
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 24;
pfd.iLayerType = PFD_MAIN_PLANE;
SetPixelFormat(hdc,ChoosePixelFormat(hdc, &pfd),&pfd);
hrc = wglCreateContext(hdc); // create current rendering context
if(hrc == NULL)
{
ShowMessage("Could not initialize OpenGL Rendering context !!!");
Application->Terminate();
}
if(wglMakeCurrent(hdc, hrc) == false)
{
ShowMessage("Could not make current OpenGL Rendering context !!!");
wglDeleteContext(hrc); // destroy rendering context
Application->Terminate();
}
glViewport(0,0,xs,ys);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
// GL exit
wglMakeCurrent(NULL, NULL); // release current rendering context
wglDeleteContext(hrc); // destroy rendering context
// release buffers
if (scr){ delete scr; scr=NULL; }
if (bmp){ delete bmp; bmp=NULL; }
if (txr){ delete[] txr; txr=NULL; }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
gl_draw();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
if (Visible) Visible=false; // hide
gl_draw();
}
//---------------------------------------------------------------------------
Единое приложение Form VCL с одним таймером.Это создает контекст GL и при первой возможности становится невидимым.Затем он периодически перезаписывает рабочий стол с черным фоном и белой рамкой прямоугольника ...
Так что вам нужно перенести материал VCL (Form1
и события) в вашу среду.Также вы можете добавить прозрачность в строку:
scr->Draw(0,0,bmp);
или прочитать изображение рабочего стола и использовать его в качестве фоновой текстуры для рендеринга GL.
PS,Чистый рендеринг GDI намного проще и, вероятно, быстрее, чем этот, но вам требуется GL, так что ...