Opengl
Getting to know OpenGL needs to begin with the fact that OpenGL is a
specification . Those. OpenGL only defines a set of required features. The implementation depends on the specific platform.
OpenGL is a cross-platform, independent programming language API for working with graphics. OpenGL is a low-level API, so to work with it, it is nice to have some idea about graphics in general and know the basics of linear algebra.
Naming
Let's say a few words about the naming of functions in OpenGL. First, the names of all functions provided directly by OpenGL begin with the prefix
gl . Secondly, functions defining some parameter characterized by a set of numbers (for example, a coordinate or a color) have a suffix of the form [number of parameters + type of parameters + representation of parameters].
- Number of parameters - indicates the number of parameters received. Accepts the following values: 1 , 2 , 3 , 4
- Parameter type - indicates the type of parameters received. The following values are possible: b , s , i , f , d , ub , us , ui . Those. byte (char in C, 8-bit integer), short (16-bit integer), int (32-bit integer), float (floating-point number), double (floating-point number of double precision), unsigned byte, unsigned short, unsigned int (the last three are unsigned integers)
- Parameter representation - indicates in what form the parameters are transmitted, if each number is separately, then nothing is written, but if the parameters are transmitted as an array, then the letter v is appended to the function name
Example:
glVertex3iv specifies the coordinate of a vertex consisting of three integers, passed as a pointer to an array.
Graphics
All graphic objects in OpenGL are a collection of points, lines, and polygons. There are 10 different primitives, with which all objects are built. Both 2D and 3D. All primitives, in turn, are defined by points - vertices.
- GL_POINTS - each vertex sets a point
- GL_LINES - each individual pair of vertices sets a line
- GL_LINE_STRIP - each pair of vertices defines a line (i.e. the end of the previous line is the beginning of the next)
- GL_LINE_LOOP - similar to the previous one, except that the last vertex is connected to the first and a closed figure is obtained.
- GL_TRIANGLES - each individual triple of vertices defines a triangle
- GL_TRIANGLE_STRIP - each next vertex defines a triangle together with two previous vertices (a ribbon of triangles is obtained)
- GL_TRIANGLE_FAN - each triangle is defined by the first vertex and subsequent pairs (i.e., triangles are built around the first vertex, forming something similar to the diaphragm)
- GL_QUADS - every four vertices form a quadrilateral
- GL_QUAD_STRIP - each next pair of vertices forms a quadrilateral, along with a pair of previous ones
- GL_POLYGON - sets a polygon with the number of angles equal to the number of specified vertices
To set the primitive, the
glBegin (primitive_type) ... glEnd () construction is used. Vertices are set by
glVertex * . Vertices are set counterclockwise. Coordinates are set from the upper left corner of the window. The vertex color is set with the
glColor * command. The color is specified as RGB or RGBA. The glColor * command acts on all vertices that go after until another glColor * command is encountered, or all, if there are no other glColor * commands.
Here is the code drawing a square with multi-colored vertices:
- glBegin ( GL_QUADS ) ;
- glColor3f ( 1.0 , 1.0 , 1.0 ) ;
- glVertex2i ( 250 , 450 ) ;
- glColor3f ( 0.0 , 0.0 , 1.0 ) ;
- glVertex2i ( 250 , 150 ) ;
- glColor3f ( 0.0 , 1.0 , 0.0 ) ;
- glVertex2i ( 550 , 150 ) ;
- glColor3f ( 1.0 , 0.0 , 0.0 ) ;
- glVertex2i ( 550 , 450 ) ;
- glEnd ( ) ;
')
OpenGL Program Basics
For platform-independent work with windows, you can use the library
GLUT . GLUT makes it easy to work with OpenGL.
To initialize GLUT at the beginning of the program, you must call
glutInit (& argc, argv) . To set the display mode, call
glutInitDisplayMode (mode) , where the mode can take the following values:
- GLUT_RGBA - includes a four-component color (used by default)
- GLUT_RGB is the same as GLUT_RGBA
- GLUT_INDEX - includes indexed color
- GLUT_DOUBLE - turns on the double screen buffer
- GLUT_SINGLE - enables a single screen buffer (by default)
- GLUT_DEPTH - includes Z-buffer (depth buffer)
- GLUT_STENCIL - includes stencil buffer
- GLUT_ACCUM - includes accumulation buffer
- GLUT_ALPHA - includes alpha blending (transparency)
- GLUT_MULTISAMPLE - enables multisampling (anti-aliasing)
- GLUT_STEREO - includes stereo image
To select multiple modes at the same time you need to use bitwise OR '|'. For example: glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH) includes double buffering, Z-buffer and four-component color. Window sizes are set by
glutInitWindowSize (width, height) . Its position is
glutInitWindowPosition (x, y) . A window is created
using the glutCreateWindow function
(window_title) .
GLUT implements an event-driven mechanism. Those. there is a main loop that starts after initialization, and all declared events are already processed in it. For example, pressing a key on the keyboard or moving the mouse cursor, etc. You can register event handler functions using the following commands:
- void glutDisplayFunc (void (* func) (void)) - sets the image drawing function
- void glutReshapeFunc (void (* func) (int width, int height)) - sets the window resize handling function
- void glutVisibilityFunc (void (* func) (int state)) - sets the window visibility state change handling function
- void glutKeyboardFunc (void (* func) (unsigned char key, int x, int y)) - sets the keystroke handling function (only those that generate ascii characters)
- void glutSpecialFunc (void (* func) (int key, int x, int y)) - sets the keyboard keystroke handling function (those that do not generate ascii characters)
- void glutIdleFunc (void (* func) (void)) - sets the function called in the absence of other events
- void glutMouseFunc (void (* func) (int button, int state, int x, int y)) - sets the function that handles mouse commands
- void glutMotionFunc (void (* func) (int x, int y)) - sets the function that handles the movement of the mouse cursor when a mouse button is held down
- void glutPassiveMotionFunc (void (* func) (int x, int y)) - sets the function that handles the movement of the mouse cursor when no mouse button is pressed
- void glutEntryFunc (void (* func) (int state)) - sets the function that handles the movement of the cursor outside the window and its return
- void glutTimerFunc (unsigned int msecs, void (* func) (int value), value) - sets the function to be called by timer
Then you can run the main loop
glutMainLoop () .
First program
Now we know the basics of working with OpenGL. You can write a simple program to consolidate knowledge.
To begin with, you need to include the GLUT header file:
- #if defined (linux) || defined (_WIN32)
- #include <GL / glut.h> / * For Linux and Windows * /
- #else
- #include <GLUT / GLUT.h> / * For Mac OS * /
- #endif
Now we already know what to write in main. We register two handlers: for drawing the contents of the window and processing its resizing. These two handlers are essentially used in any program that uses OpenGL and GLUT.
- int main ( int argc , char * argv [ ] )
- {
- glutInit ( & argc , argv ) ;
- glutInitDisplayMode ( GLUT_DOUBLE | GLUT_RGBA ) ; / * Include double buffering and four-component color * /
- glutInitWindowSize ( 800 , 600 ) ;
- glutCreateWindow ( "OpenGL lesson 1" ) ;
- glutReshapeFunc ( reshape ) ;
- glutDisplayFunc ( display ) ;
- glutMainLoop ( ) ;
- return 0 ;
- }
Now you need to write a function to handle window resizing. Set the display area to the size of the entire window using the
glViewport command (x, y, width, height) . Then we load the projection matrix
glMatrixMode (GL_PROJECTION) , replace it with the unit
glLoadIdentity () and set the orthogonal projection. Finally, let's load the glMatrixMode model-
view matrix
(GL_MODELVIEW) and replace it with the one.
As a result, we get:
- void reshape ( int w , int h )
- {
- glViewport ( 0 , 0 , w , h ) ;
- glMatrixMode ( GL_PROJECTION ) ;
- glLoadIdentity ( ) ;
- gluOrtho2D ( 0 , w , 0 , h ) ;
- glMatrixMode ( GL_MODELVIEW ) ;
- glLoadIdentity ( ) ;
- }
It remains only to write a function to draw the contents of the window. We will draw the square that I gave above as an example. Add have quite a bit of code. First, before drawing, you need to clear the various buffers with
glClear (mode) . Used as well as glutInitDisplayMode. Possible values:
- GL_COLOR_BUFFER_BIT - to clear the color buffer
- GL_DEPTH_BUFFER_BIT - to clear the depth buffer
- GL_ACCUM_BUFFER_BIT - to clear the accumulation buffer
- GL_STENCIL_BUFFER_BIT - for cleaning the stencil buffer
In our case, you need to clear only the color buffer, since we do not use others. Secondly, after drawing, you need to ask OpenGL to change screen buffers with
glutSwapBuffers () , because we have double buffering enabled. Everything is drawn on a hidden buffer from the user and then the buffers are changed. This is done to get a smooth animation and to avoid the screen
flicker effect.
We get:
- void display ( )
- {
- glClear ( GL_COLOR_BUFFER_BIT ) ;
- glBegin ( GL_QUADS ) ;
- glColor3f ( 1.0 , 1.0 , 1.0 ) ;
- glVertex2i ( 250 , 450 ) ;
- glColor3f ( 0.0 , 0.0 , 1.0 ) ;
- glVertex2i ( 250 , 150 ) ;
- glColor3f ( 0.0 , 1.0 , 0.0 ) ;
- glVertex2i ( 550 , 150 ) ;
- glColor3f ( 1.0 , 0.0 , 0.0 ) ;
- glVertex2i ( 550 , 450 ) ;
- glEnd ( ) ;
- glutSwapBuffers ( ) ;
- }
Total
Everything! You can compile. It should get something like this:
The entire code is complete (for those who have not mastered the article).
In principle, there is nothing difficult in this, at least if you have already encountered graphics before.
OpenGL is a handy tool for creating cross-platform applications using graphics. OpenGL is easy to use with the programming language that is more convenient for you. There are bindings to OpenGL for many popular languages, such as C, C ++, C #, Java, Python, Perl, VB, and others. View information about them on the
official website of OpenGL .