I. Preface
When learning OpenGL, we found that many functions are global. In the previous chapters, we used to draw images in a window DC. How do we deal with drawing in multiple windows? There are a variety of online methods, one of which is used here. The wglmakecurrent function is used to switch between different windows, so that multiple windows can be simultaneously blurred.
2. Preparation
Each window is bound to OpenGL through the following processes:
1. Get the window handle/hwnd (the classes inherited by twincontrol can all be obtained through twincontrol. handle, and the MFC window can be obtained through cwnd: getsafehwnd)
2. Get the HDC of the device scenario through the handle (obtained through API getdc)
3. Obtain hglrc of OpenGL through HDC in device scenarios (obtained through wglcreatecontext () of OpenGL)
Of course, remember to release the corresponding hglrc and window DC when the program is destroyed. You can store the information in the array through the above correspondence. Taking four windows as an example, I created several arrays as follows:
FDC: array[0..3] of HDC; FHRC: array[0..3] of HGLRC; FHwnd: array[0..3] of THandle;
Iii. Initialization
In this example, multiple tpanels are used as an example to replace multiple Windows. The preceding three arrays are initialized. An inidc () method is created and called in oncreate of the window to initialize the value of the array variable.
Procedure tform1.formcreate (Sender: tobject); begin fbmpindex: = 0; // initialize multiple windows in inidc (0, pnl1.handle); inidc (1, pnl2.handle); inidc (2, pnl3.handle); inidc (3, pnl4.handle); end;
The following inidc code
Procedure tform1.inidc (I: integer; hform: thandle); var PFD: tpixelformatdescriptor; pixelformat: integer; begin with PFD do begin nsize: = sizeof (tpixelformatdescriptor); // size nversion: = 1; // version dwflags: = pfd_support_opengl or pfd_draw_to_window or pfd_doublebuffer; // support double-buffering ipixeltype: = pfd_type_rgba; // color type ccolorbits: = 24; // preferred color depth credbits: = 0; credshift: = 0; // color bits (ignored) cgreenbits: = 0; cgreenshift: = 0; cbluebits: = 0; cblueshift: = 0; calphabits: = 0; calphashift: = 0; // No Alpha buffer caccumbits: = 0; caccumredbits: = 0; // no accumulation buffer, caccumgreenbits: = 0; // accum bits (ignored) caccumbluebits: = 0; caccumalphabits: = 0; cdepthbits: = 16; // depth buffer cstencilbits: = 0; // No stenpencil buffer cabuffers: = 0; // No auxiliary buffers ilayertype: = pfd_main_plane; // main layer breserved: = 0; dwlayermask: = 0; dwvisiblemask: = 0; dwdamagemask: = 0; end; FDC [I]: = getdc (hform); fhwnd [I]: = hform; pixelformat: = choosepixelformat (FDC [I], @ PFD); If pixelformat = 0 Then exit; if not setpixelformat (FDC [I], pixelformat, @ PFD) Then exit; fhrc [I]: = wglcreatecontext (FDC [I]); wglmakecurrent (FDC [I], fhrc [I]); // set the background color to the Black parameter rgba glclearcolor (0, 0, 0, 0); end;
4. Drawing
Modify the draw function in the previous chapter to support multi-window painting. The Code is as follows:
Procedure tform1.draw (I: integer); var BMP: tbitmap; texture: gluint; L, t, W, H: integer; RC: trect; begin // reset the wglmakecurrent (FDC [I], fhrc [I]) in the display area; // recalculate and set the display area size getwindowrect (fhwnd [I], RC ); w: = RC. right-RC. left; H: = RC. bottom-RC. top; glmatrixmode (gl_projection); glloadidentity; glviewport (0, 0, W, H); gluortho2d (0, W, H, 0); glmatrixmode (gl_modelview); glloadidentity; // only to display multiple images, not required Required Inc (fbmpindex); BMP: = tbitmap. create; BMP. loadfromfile (extractfilepath (paramstr (0) + inttostr (fbmpindex mod 3) + '.bmp '); // create a texture region glgentextures (1, @ texture ); // bind the texture area glbindtexture (gl_texture_2d, texture); // use a bitmap to create an image texture glteximage2d (gl_texture_2d, // The texture is a 2D Texture gl_texture_2d 0, // The image detail level defaults to 0 3, // the score of the data. Because the image is composed of three types: Red, green, and blue, the default value is 3 BMP. width, // The width of the texture. BMP. height, // The texture height is 0, // The Border Value defaults to 0 gl_bgr_ext, // the data format BMP uses BGR gl_unsigned_byte, // The data that makes up the image is a BMP of the unsigned byte type. scanline [BMP. height-1] // Dib Data Pointer); // The following two lines let OpenGL enlarge the original texture (gl_texture_mag_filter) or reduce the original texture (gl_texture_min_filter) openGL adopts the filtering method. // Gl_linear uses linear filtering to smooth the image processing, but requires more memory and CPU gltexparameteri (gl_texture_2d, cosine, gl_linear); // linear filtering gltexparameteri (gl_texture_2d, cosine, cosine, gl_linear); // linear filtering // The following is a drawing. Use a quadrilateral to draw an image // enable texture ing if glisenabled (gl_texture_2d) = 0 then glable (gl_texture_2d ); // clear the buffer glclear (gl_color_buffer_bit or gl_depth_buffer_bit); L: = 10; T: = 10; W: = 100 + (I * 50); // zoom in to 200*2 00 image // select texture if multiple textures are used in the scenario, the texture glbindtexture (gl_texture_2d, texture) cannot be bound between glbegin () and glend (); glbegin (gl_quads ); // The first parameter of gltexcoord2f is the X coordinate. // 0.0 is the left side of the texture. 0.5 is the midpoint of the texture, and 1.0 is the right side of the texture. // The second parameter of gltexcoord2f is Y coordinate. // 0.0 is the bottom of the texture. 0.5 is the midpoint of the texture, and 1.0 is the top of the texture. Gltexcoord2f (0, 1); glvertex2f (L, t); gltexcoord2f (1, 1); glvertex2f (L + W, T); gltexcoord2f (1, 0 ); glvertex2f (L + W, T + W); gltexcoord2f (0, 0); glvertex2f (L, t + W); glend (); BMP. free; swapbuffers (FDC [I]); end;
The code for the image above, if you think it looks complicated, you can use the following simple code:
Procedure tform1.drawsimple (I: integer); var L, t, W, H: integer; RC: trect; begin // reset the display area wglmakecurrent (FDC [I], fhrc [I]); // recalculate and set the display area size. getwindowrect (fhwnd [I], RC); W: = RC. right-RC. left; H: = RC. bottom-RC. top; glmatrixmode (gl_projection); glloadidentity; glviewport (0, 0, W, H); gluortho2d (0, W, H, 0); glmatrixmode (gl_modelview); glloadidentity; // clear the buffer glclear (gl_color_buffer_bit or gl_depth_buffer_bit); // set the color of the Quadrilateral glcolor3f (1, 0.5, 0); // draw the first polygon L: = 10; t: = 10; W: = 64 + (I-2) * 50; glbegin (gl_quads); glvertex2f (L, t); glvertex2f (L + W, t ); glvertex2f (L + W, T + W); glvertex2f (L, t + W); glend (); swapbuffers (FDC [I]); end;
For ease of demonstration, here we use a timer ttimer to replace the previous onpaint painting in the window. The code for the timer is as follows:
procedure TForm1.tmr1Timer(Sender: TObject);begin Draw(0); Draw(1); DrawSimple(2); DrawSimple(3);end;
5. Release
Finally, remember to release resources. In Delphi, basically all resources applied for must be recycled. New-> delete/dispose, get-> release, create-> destroy, in short, create) to destroy (destroy), borrow (get) to return (release ).
procedure TForm1.FormDestroy(Sender: TObject);var i: Integer;begin for i := 0 to 4 - 1 do begin wglMakeCurrent(FDC[i], FHRC[i]); wglDeleteContext(FHRC[i]); ReleaseDC(fhwnd[i], FDC[i]); end;end;
The effect is as follows:
Source code download: opengl_06.zip
2014-07-17 by Lin