1. Necessary work before drawing
1.1 set the view area of the form (view port)
Glviewport (X: glint; Y: glint; width: glsizei; Height: glsizei );
The parameters X and Y specify the position in the window in the lower-left corner of the visible area. Generally, they are (0, 0), and width and height specify the width and height of the visible area. Note that the window coordinates used by OpenGL are different from those used by windowsgdi.
|
|
Form coordinates in windowsgdi |
Format coordinates defined by OpenGL |
1.2 create a projection transformation
Next, we need to set a projection transformation. Projection transformations include parallel projection and Perspective Projection. In parallel projection, objects are of the same size regardless of distance, while in Perspective Projection, objects are of the opposite size. Therefore, perspective projection is more like what our eyes see. But in some special cases, parallel projection still plays a role, for example, 3D touch creation program.
1.2.1 create parallel projection
Glortho (left, right, bottom, top, znear, zfar: gldouble );
Left specifies the leftmost plane of the parallel projection;
Right specifies the rightmost plane of the parallel projection;
Bottom specifies the bottom plane of the parallel projection;
Top specifies the top plane of the parallel projection;
Znear and zfar specify the near trim plane and the far building plane.
Use the following code to create a parallel projection:
Glmatrixmode (gl_projection );
Glortho (-clientwidth Div 2, clientwidth Div 2,-clientheight Div 2, clientheight Div 100 );
Glmatrixmode (gl_modelview );
In the above code, you can see a strange function: glmatrixmode. It tells OpenGL that we will set the projection transformation matrix next.
1.2.2 create a Perspective Projection
Perspective Projection shortens or compresses distant objects based on distance. This makes objects in the distance look smaller and more real. As the distant scenes are smaller, as the distance increases, the observer should be able to see more scenes. Therefore, the visible area of the perspective projection should be the geometric shape of a flattened part. 3.1-6.
|
Figure 3.1-6 pivot projection |
Similar to line projection, you only need to call the glortho function to glfustum or gluperspective.
Gluperspective (fovy, aspect, znear, zfar: gldouble );
Among them, fovy is the angle of the visible area in the vertical direction (that is, the two corners of the top and bottom trim planes );
Aspect is the ratio of height to width (that is, the ratio of width to height );
Znear and zfar are near and far trim planes.
|
HTTP header defined by gluperspective |
The following code defines Perspective Projection:
Glmatrixmode (gl_projection );
Gluperspective (60, clientwidth/clientheight, 1, zfar );
Glmatrixmode (gl_modelview );
Zfar sets different values based on the size of the scenario to be drawn.
1.3 set the background color
This step is optional. We can call the glclearcolor function to set the color used to clear the screen and buffer.
Glclearcolor (R, G, B, A: glfloat );
Here, R, G, B, And a represent the R, G, B, and transparency values of colors respectively. The value range is 0-1. For example, the following code sets the background color to Black:
Glclearcolor (0, 0, 0, 1 );
1.4 clear screen and buffer before painting
Generally, we write the call of all the plotting functions in the renderscene process. We should clear the screen and buffer before each draw. The following code uses the specified clear color to clear them:
Void renderscene
{
Glclear (gl_color_buffer_bit or gl_depth_buffer_bit );
... Drawing...
}
2. Use OpenGL to draw basic elements
All complicated things are composed of simple and basic elements. In OpenGL, the basic elements that constitute complex graphics are converted into elements. After learning how to draw basic elements, You can plot any complex objects.
OpenGL provides the following elements:
Point
Line
Continuous Line
Closed line
Triangle
Triangle Bar
Triangle slice
Quadrilateral
Polygon
2.1 draw a triangle
Before and after glvertex is called, we need to call the glbegin and glend functions to identify the beginning and end of the element.
When calling the glbegin function, we need to input a parameter to tell OpenGL what type of elements we will draw. The input gl_triangles indicates that we will draw a triangle. For example:
Glbegin (gl_triangles );
Glvertex (1, 0, 1 );
Glvertex (0, 0 );
Glvertex (1, 1, 0 );
Glend;
A triangle with vertices (, 1), (, 0), and (, 0) is drawn.
2.2 draw a Triangle Bar
Just set the glbegin parameter to gl_triangle_strip. For example:
Glbegin (gl_triangle_strip );
Glvertex (1, 0, 1 );
Glvertex (0, 0 );
Glvertex (1, 1, 0 );
Glvertex (1, 3, 0 );
Glvertex (4,8, 2 );
Glend;
2.3 draw triangle slices
Just set the glbegin parameter to gl_triangle_fan. Since the rendering method is roughly the same, I will not give an example here.
2.4 draw points, lines, continuous lines, and closed lines
The following lists the values that should be passed to glbegin to draw these elements.
Point: gl_points
Line: gl_lines
Continuous Line: gl_line_strip
Closed line: gl_line_loop
It is worth noting that the elements gl_line_strip and gl_line_loop.
The principles of gl_line_strip and gl_triangle_strip are the same. That is, starting from the first vertex, the nth vertex and n-1 form a straight line. For example:
Glbegin (gl_line_strip );
Glvertex (A. X, A. Y, A. z );
Glvertex (B. X, B. Y, B. Z );
Glvertex (C. X, C. Y, C. z );
Glend;
Two line segments will be drawn: Line Segments AB and line segments BC.
The element gl_line_loop is built on the basis of gl_line_strip. Unlike gl_line_strip, gl_line_loop connects a straight line between the last vertex and the first vertex to form a closed image. If you set the gl_line_strip parameter of the above Code to gl_line_loop, three line segments will be drawn: Line Segments AB, BC, and Ca.
2.5 draw a quadrilateral and polygon
Quadrilateral (QUAD) is also an element with a high probability of use. You only need to change the glbegin parameter to gl_quads to draw a quadrilateral. If you change the parameter to gl_polygon, you can draw a polygon.
However, if you observe it carefully, you will find that, no matter the quadrilateral or polygon, they can all be represented by triangles after a little effort. In addition, because the current video card has made a lot of Optimizations to the triangle painting, the speed of triangle painting is much faster than that of polygon. Therefore, do not use polygon elements to increase rendering speed.
If you want to use a quadrilateral or polygon, pay attention to the following points:
1. A polygon drawn using OpenGL must be a convex polygon;
2. All vertices of the drawn polygon must be in the same plane.
These restrictions make it inconvenient to draw a polygon. This also highlights the advantages of using triangles-you never have to worry that the drawn triangles are invalid. You can use triangles to draw complex polygon.
3. Use deep Testing
We know that when a plane or object blocks another object, the objects behind it are invisible. At this point, we should avoid plotting the objects behind it. At this time, we can use a function of OpenGL: Depth test (also known as the depth buffer (Z-buffer) to remove these blocked surfaces. In the depth test, the distance between the object represented by the pixel and the observer is calculated when the pixel is drawn, which is called the Z value. If the value is the smallest of all Z values in the same pixel, draw the pixel. Otherwise, Skip. This is an effective solution to deep problems. We only need to call the Function
Glenable (gl_depth_test );
You can enable the deep test. Call
Gldisable (gl_depth_test );
Disable the deep test.
4 remove the back
If you want to draw some solid objects, the surface inside the solid object will never be visible. While OpenGL does not know that these aspects are invisible, it will still calculate and draw them. Although the back is still not drawn on the screen, it is a waste of unnecessary time. Therefore, we should turn on the back hide function to remove these invisible surfaces.
Bypass
If we send an object to the external surface in a counter-clockwise order to OpenGL, OpenGL considers this surface as an external surface. At this time, we can enable the backend removal function without any impact. However, if you do not comply with this rule, you can enable the backend removal, and you will not get the correct rendering result. We can change this rule by calling the glfrontface function. For example:
Glfrontface (gl_ccw );
It will make OpenGL think that all the surface that is wound counterclockwise is positive. If gl_ccw is changed to gl_cw, OpenGL will think that all the surfaces that are wound counterclockwise are positive.
Enable Surface Removal
Before rendering, add the following code to enable Surface Removal:
Glcullface (gl_back); // hide the back. If you change the parameter to gl_front, the front is hidden.
Glable (gl_cull_face );
Disable Surface Removal
Some objects, whether on the front or back, may be visible (for example, a piece of paper with both the front and back). When rendering these objects, we should close the surface removal. Just add the following code:
Gldisable (gl_cull_face );
5. display the rendering result to the screen.
After the rendering of all objects is complete, we need to call the swapbuffers function to display the rendering result: