OpenGL programming in Visual C
2004-01-10 ■ HY ■ Forum
From the Yesky
OpenGL is very convenient, so it is increasingly popular, but for many people, it is carried out on the microcomputer. The first question is to adapt to the microcomputer environment. This is often the most critical step, although it is also the most primary. In general, I don't recommend using the GLUT package. It is difficult to give full play to the function on the interface of Windows.
The following describes how to make OpenGL program on VC . The general process of OpenGL drawing can be seen as such, first painted in OpenGL's Draw Environment RenderContext (RC), then pass the drawing environment of the operating system to the operating system Drawing Environment DEVICECONTEXT (DC) In the middle, it is actually drawn to the screen.
The following is to draw a Bezier curve as an example to detail the method of OpenGL programming on VC . Detailed annotations are given in the text to give beginners clear guidelines. Step step by step, you will have a graphic that will smoothly draw the first OpenGL platform.
First, generate program framework test.dsw
New Project | MFC Application Wizard (EXE) | "TEST" | OK * Note *: Add "" "
Second, import the documentation of Bezier curve
BEZIERCURVE.H beziercurve.cpp is generated by the following method:
Workspace | ClassView | TEST CLASSES |
Third, editing the definition and implementation of Bezier curve class
Write the following two files:
Beziercurve.h beziercurve.cpp
Fourth, set the compilation environment:
1. In Beziercurve.h and TestView.h, plus:
#include
#include
2. In the integrated environment
Project | Settings | LINK | Object / Library Module | "OpenGL32.LIB Glu32.lib Glaux.lib" | OK
V. Set the OpenGL work environment: (each of the following operations is targeting TestView.cpp)
1. Process precreateWindow (): Set the style of OpenGL drawing window
CS.Style | = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CS_OWNDC;
2. Handling onCreate (): Create OpenGL's drawing device.
The mechanism of OpenGL drawing is: first use OpenGL's drawing context rendering context to pass the picture, then pass the draws to the Window's drawing context Device Context (Amunicate as DC). Pay attention to In the process of running, there can be multiple DCs, but there can be only one RC. Therefore, when a DC draws, release the RC immediately so that other DCs are also used. In the following code, there will be detailed comments.
int CTestView :: OnCreate (LPCREATESTRUCT lpCreateStruct) {if (CView :: OnCreate (lpCreateStruct) == -1) return -1; myInitOpenGL (); return 0;} void CTestView :: myInitOpenGL () {m_pDC = new CClientDC (this ); // Create DC assert (m_pdc! = Null); if (! Mysetuppixelformat ()) // Sets the bitmap format of the drawing, the function is listed below;
m_hrc = wglcreateContext (m_pdc-> m_hdc); // Create RC WGLMAKECURRENT (m_pdc-> m_hdc, m_hrc); // RC is associated with current DC
} // cclient * m_pdc; hglrc m_hrc; is a member variable of CTestView
Bool ctestview :: myseTuppixelformat () {// We temporarily regardless of the specific content of the format, and later familiar with the re-change format
static PIXELFORMATDESCRIPTOR pfd = {sizeof (PIXELFORMATDESCRIPTOR), // size of this pfd 1, // version number PFD_DRAW_TO_WINDOW | // support window PFD_SUPPORT_OPENGL | // support OpenGL PFD_DOUBLEBUFFER, // double buffered PFD_TYPE_RGBA, // RGBA type 24, // 24-Bit Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, // No alpha buffer 0, // shift bit ignored 0, // no Accumulation Buffer 0, 0, 0, 0 , // 32-bit z-buffer 0, // no stencil buffer 0, // no auxiliary buffer pfd_main_plane, // main layer 0, // reserved 0, 0, 0 // Layer Masks Ignored}; int pixelformat;
IF ((Pixelformat = choosepixelformat (m_pdc-> m_hdc, & pfd) == 0) {MessageBox ("choosepixelformat failed); return false;}
IF (setpixelformat (m_pdc-> m_hdc, pixelformat, & pfd) == false) {MessageBox ("setpixelformat failed"; Return False;}
Return True;
}
3. Handle ONDSTROY ()
Void ctestview :: ONDESTROY () {wglmakecurrent (m_pdc-> m_hdc, null); // Release RC WGLDeleteContext (m_hrc) corresponding to M_HDC; // Delete RC IF (M_PDC) delete m_pdc; // Delete DC owned by the current view CView :: ONDESTROY ();
4. Handle OneRaseBkGnd ()
Bool CTestView :: OneRaseBkgnd (CDC * PDC) {// Todo: add your message handler code Here and / or call default // Return CView :: OneRaseBkGnd (PDC); // Turn this sentence, if not, Window // will be refreshed with white northern view, causing the screen to flash Return True; // as long as it returns. } 5. Processing onDraw ()
Void ctestview :: OnDraw (CDC * PDC) {WGLMAKECURRENT (m_pdc-> m_hdc, m_hrc); // Make RC associated with the current DC with MyDrawScene (); // Draw SwapBuffers in RC (m_pdc-> m_hdc); // Put the RC to the current DC, and // displays WGLMakeCurrent (m_pdc-> m_hdc, null) on the screen; // Release the RC, so that other DC draws
}
Void ctestview :: mydrawscene () {GlclearColor (0.0F, 0.0F, 0.0F, 1.0F); // Setting the background color to black glclear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLPUSHMATRIX (); GLTranslated (0.0F, 0.0F, - 3.0F); // translate the object in the direction of (0, 0, -1) // instead of projection. Because the default viewpoint is (0, 0, 0), only the shift // object is visible. // This example is to demonstrate the plane Bezier curve, as long as a rotation / / transformation can be more clearly seen.
// Draw a bezier curve bezier_curve.mypolygon (); // draws the control polygon of the Bezier curve bezier_curve.mydraw (); // cbeziercurve bezier_curve // is the member variable of CTestView / / Specific function See Appendix GLPopMatrix (); GLFLUSH (); // End RC drawing return;
}
6. Handle Onsize ()
Void ctestview :: Onse (uint ntype, int cx, int CY) {cview :: Onsize (NTYPE, CX, CY); Verify (WGLmakecurrent (m_hrc)); // Confirm that RC is associated with the current DC associated W = CX; h = cy; verify (wglmakecurrent (null, null)); // confirm that DC release rc}
7 handle ONLBUTTONDOWN ()
Void ctestview :: ONLBUTTONDOWN (UINT NFLAGS, CPOINT) {cView :: ONLBUTTONDOWN (NFLAGS, POINT); if (bezier_curve.m_n> max-1) {MessageBox ("The number of vertices exceeds maximum max = 50"); Return;}
/ / The following is the coordinate transformation to prepare getClientRect (& m_clientRect); // Get viewport area size W = m_clientRect.right-m_clientRect.Les; // View port width w h = m_clientRect.bottom-m_clientRect.top; // Viewport Height h // w, H is CTestView member variable centerx = (m_clientRect.Left m_clientRect.right) / 2; // central location, centery = (m_clientRect.top m_clientRect.bottom) / 2; // Take it Original // CENTERX, CENTERY is a member variable of CTestView GLDOUBLE TMPX, TMPY ;TMPX = SCRX2GLX (Point.x); / / On-screen coordinates Translate into OpenGL drawing specification coordinate TMPY = scry2gly (point2gly (Point.y);
Bezier_curve.m_vertex [bezier_curve.m_n] .x = tmpx; // Add a vertex bezier_curve.m_vertex [bezier_curve.m_n] .y = tmpy;
Bezier_curve.m_n ; // vertex number plus an invalidateRect (null, true); // Send refresh redraw message
}
Double CTestView :: Scrx2glx (int SCRX) {Return (SCRX-CENTERX) / DOUBLE (H);}
Double CTestView :: scry2gly (int scry) {}
appendix:
1.cbeziercurve's statement: (BezierCurve.h)
Class cbeziercurve {public: mypoint2d m_vertex [max]; // Control the vertex, with array storage // mypoint2d is a two-dimensional structure // member for GLDOUBLE X, Y INT m_n; // Control the number of PUBLICs: Cbeziercurve (); virtual ~ cbeziercurve (); void bezier_generation (mypoint2d p [max], int level); // algorithm specific implementation VOID myDraw (); // Painting Function Void MyPolygon (); // Painting Control Polygon} ;
2. Implementation of CbezierCurve: (Beziercurve.cpp)
Cbeziercurve :: cbeziercurve () {m_n = 4; m_vertex [0] .x = -0.5F; m_vertex [0] .y = -0.5f; m_vertex [1] .x = -0.5f; m_vertex [1] .y = 0.5F; m_vertex [2] .x = 0.5f; m_vertex [2] .y = 0.5f; m_vertex [3] .x = 0.5f; m_vertex [3] .y = -0.5f;}
Cbeziercurve :: ~ cbeziercurve () {}
Void cbeziercurve :: mydraw () {bezier_generation (m_vertex, level); -; if (Level <0) return; if (level == 0) {Glcolor3f (1.0F, 1.0F, 1.0F); Glbegin (GL_LINES); // Draw line segment glvertex2d (p [0] .x, p [0] .y); GLVERTEX2D (p [m_n-1] .x, p [m_n-1] .y); glend (); // End the line segment return; // Regeneration to the bottom, jump out of the recursive} mypoint2d Q [max], r [max]; for (i = 0; i {q [i] .x = p [i] .x; q [i] .y = p [i] .y;}
For (i = 1; i
Bezier_Generation (Q, Level); Bezier_Generation (R, Level);
}
Void cbeziercurve :: mypolygon () {glbegin (GL_LINE_STRIP); / / Picture Link Segment Glcolor3f (0.2F, 0.4F, 0.4F); for (int i = 0; i