--------------------------------------------------------------------------------------------------------------- ----------------
Just like learning other programming languages, in order to write down the first OpenGL program
We must take pains to pave the bricks first, set up a good environment ...
So let me first put the environment of the required library, and then start coding.
--------------------------------------------------------------------------------------------------------------- ----------------
"Installation Environment"
It would have been nice to simply use the glut and glew libraries, but to match the example of the book, I decided to configure it with the eighth edition of the OpenGL Programming Guide.
About this configuration, I found a predecessor has put the detailed process written in his CSDN blog, we can go to see, very simple, there are source code.
http://blog.csdn.net/qq821869798/article/details/45247241
In addition, in order to not need each new project to be configured once, I directly copy the Include and Lib directory files to the vs2012 installation directory
For example my directory is C:\Program Files (x86) \microsoft Visual Studio 11.0\VC
Copy to the directory under the corresponding include and LIB, it is possible. You don't have to repeat those steps every time you create a new project.
Next, write down the OpenGL program verification. I will try to comment on the code, I hope you can see clearly.
--------------------------------------------------------------------------------------------------------------- ---------------
In fact, I always thought that the code to run first and then carefully study the code will be more clear, so I first presented the book the first example of the results of the operation.
--------------------------------------------------------------------------------------------------------------- -----------------
If your environment is properly configured and the code is hit by the book, it may stop running after running.
Glutinitcontextversion (4, 3); This line of code comments can be resolved, temporarily do not know why, see if you can find an explanation.
--------------------------------------------------------------------------------------------------------------- -----------------
As the book says, creating Windows, receiving mouse and keyboard input, and so on, are not OpenGL, just using third-party repositories,
As the examples use glut, glew, these tools simplify our development, allowing us to focus more on the nature of OpenGL.
First the header file and some variable definitions
#include <iostream>using namespace std; #include "vgl.h" #include "LoadShaders.h" enum Va0_ids {triangles, Numvaos} ; enum Buffer_ids {ArrayBuffer, numbuffers};enum attrib_ids {vposition = 0, Vcolor = 1}; Gluint Vaos[numvaos]; Gluint buffers[numbuffers];const Gluint numvertices = 6;
Then go to the main function and see what the main thing is.
int main (int argc, char** argv) {/** The function is used to initialize the glut library, and then interacts with the current window System for command-line arguments, you can specify the window size, position, or color type so glutinitwindowsize, Glutinitdisplaymode or glutinitwindowposition can be run before glutinit but when the command line has parameters, Glutinit removes the previous action, such as setting the window size, and so on. */glutinit (&ARGC, argv);/** This function specifies the window color type in addition to the Glut_rgba (specify the RGBA color mode window), there are other types, such as Glut_rgb (Specify the RGB color mode window), GLU T_depth (window using deep cache), Glut_stencil (window using template cache), etc. can be consulted GLUT document HTTPS://WWW.OPENGL.ORG/DOCUMENTATION/SPECS/GLUT/SPEC3/ Node12.html#section00033000000000000000*/glutinitdisplaymode (Glut_rgba);/** The next two functions look at their names and know their purpose is to set the window size and the window position, but we still have to set the actual device size dynamic setting is better */glutinitwindowsize (glutinitwindowposition); (300, 300);/** from the name, using a specific version of OpenGL but I use 4.3 when the run will crash into 3.0 after the reason unknown origin. */glutinitcontextversion (3, 0); After/**opengl3.2, two modes of compatibility mode compatibility profile are proposed, which guarantees that all features after 1.0 can be used. Core profile, this mode ensures that only the latest features *///glutinitcontextprofile (glut_core_profile) are used,//glutinitcontextprofile (glut_ Compatibility_profile);/** creates a window with the window caption created by the window that is associated with the OpenGL context environment the function API official description: The display stateOf a window is initially for the window to be shown. But the window's display state was not actually acted upon until Glutmainloop was entered. This means until Glutmainloop was called, rendering to a created window was ineffective because the window can not yet be di Splayed. Simply put, the rendering of the window works after the Glutmainloop function is executed. If you do not call Glutmainloop, the window is not displayed. */glutcreatewindow (argv[0]); if (!gl_arb_vertex_array_object) std::cout << "Glew_arb_vertex_array_object not Available. "<< std::endl;/** This function belongs to another auxiliary library Glew (OpenGL Extension Wrangler), which is an extension library for C/s + +, which allows us to obtain various functions of the OpenGL extension. And here's what happens under OpenGL under Windows. The evil of Microsoft to push its own D3D, so the default support for OpenGL is very limited. Since the openGL1.1 version has never been upgraded, almost more than 10 years. So now in Windows for OpenGL support, all rely on the graphics card manufacturers. Because of this, it is also very necessary to update to the latest graphics drivers. For a different video card, support openGL1 version is not the same, the specific needs of the website to view. My GT750, for example, supports openGL4.3 although the latest OpenGL is supported after the driver is installed, Microsoft does not provide a direct OpenGL API, which makes it cumbersome to use. As a result, the usefulness of Glew, he is actually the packaging of these cumbersome things, so that programmers can easily call glxxx OpenGL function. So, Glew simplifies the process of getting the address of a function, reducing our workload! So after this function is initialized, we can easily use the relevant GL function in the subsequent code. */if (Glewinit ()) {Cerr << unable to InitialiZe glew exiting "<< endl;exit (exit_failure);} /** These functions I added myself, you can get the OpenGL information in your system by: */const char* Version = (const char*) glgetstring (gl_version);p rintf (" OpenGL version:%s\n ", version), const char* extensions = (const char*) glgetstring (gl_extensions);//printf (" OpenGL extension:%s\n ", extensions); const char* renderer = (const char*) glgetstring (gl_renderer);p rintf ("OpenGL Graphics:%s\n", renderer); const Char * Vendor = (const char*) glgetstring (Gl_vendor);p rintf ("OpenGL Developer:%s\n", vendor);/** The function initializes the relevant data for OpenGL, preparing for subsequent rendering. The next step is to parse */init () in detail and/** the function to set the callback function for the window, that is, the callback function executes when the window is updated. A parameter is the address of a function, a function pointer. */glutdisplayfunc (display);/** The function is an infinite loop function, which is a dead loop. It will always handle the callback functions that have been registered, as well as user input. */glutmainloop (); return 0;}
And then we go in and initialize the function init to see
void init (void) {/** The function prototype is void Glgenvertexarrays (Glsizei N, Gluint *arrays); The function is to return n unused object names to the array arrays. As an array of vertex objects (Vertex array object), common shorthand Vao overrides. In OpenGL, Vao is responsible for managing the various data associated with the vertex (Vertices) collection. But these data are saved to the vertex cache objects (Vertex buffer object), referred to as VBO. We'll explain in more detail now we just need to know that Vao is an object that contains one or more VBOs. */glgenvertexarrays (Numvaos, Vaos);/** the function prototype is void Glbindvertexarray (Gluint array); The function is simply to bind the object (bind an object) for this function, Vaos[triangles] holds the name of the object returned after execution of the glgenvertexarrays, and it passes in the function as a parameter. At the first call, OpenGL internally allocates the memory required for this object and takes it as the current object. The book on the definition of this binding object is described by setting the switch of the railway, I think it is quite good to understand: "Once the switch is set, all trains passing through this line will sail to the corresponding track, if set to another state, then the passing of the vertical car will be driven to another track" The same is true of OpenGL, which object is currently bound, followed by actions against this object, unless another object is re-bound. In general, there are two cases where we need to bind the object: 1, create the object and initialize its corresponding data 2, the next time we are ready to use this object and it is not the currently bound object when */glbindvertexarray (Vaos[triangles]);/** Defines the coordinates of two triangles here you need to know that the current coordinate system is screen-centric, the x-axis is in the right direction, and the y-axis is heading upward. The ranges are [ -1,1], [ -1,1]*/glfloat vertices[numvertices][2] = {{ -0.90, -0.90},//Triangle 1{0.85, 0.90},{-0.90, 0.85},{ 0.90, -0.85},//Triangle 2{0.90, 0.90},{-0.85, 0.90}};/** the function prototype is void GlgenbuffERs (glsizei N, Gluint *buffers); The function is to return n the currently unused object name to the buffers array as the vertex cache object (Vertex buffer Objects), or VBO. Vbo refers to an area of memory that is allocated and managed by OpenGL server (OpenGL servers). Almost all incoming OpenGL data is stored in the VBO. */glgenbuffers (numbuffers, buffers);/** the function prototype is void Glbindbuffer (glenum target, gluint buffer); The role is to bind different types of cached objects for the currently assigned name. Simply put, the vertex cache object is initialized. Since there are many different types of cache objects in OpenGL, it is necessary to specify the corresponding type when binding the cache object, denoted by the parameter target. In this example, the vertex data is saved to the cache, so the Gl_array_buffer type is used to represent it. There are currently 8 types of cached objects, respectively, for different OpenGL function implementations. Later introduced to Vbo time to explain in detail. */glbindbuffer (Gl_array_buffer, Buffers[arraybuffer]);/** above Glbindbuffer only initialized Vbo, and the following function is the vertex data (vertex Data) is passed to the cache object. It does two things, 1. Storage space required to allocate vertex data 2, copy data from an array of applications to the OpenGL server in-memory function prototype is void Glbufferdata (glenum target, glsizeptr size, const glvoid* data, glenum usage); The type of object used to represent the cache size is used to indicate how large the data is to be stored. Also that is OpenGL memory allocated on the sub-server memory size data used to represent the data to be stored pointer usage used to set the read and write mode of OpenGL after allocating data */glbufferdata (Gl_array_buffer, sizeof ( vertices), vertices, gl_static_draw);//------------------------------------------------------------------------- --------/** The above code we created and bound the Vao and defined the topPoint data and transfer it to VBO. So at this time Vao has not been associated with VBO, at the end of the function we will elaborate. Let's look at the shader first. *///---------------------------------------------------------------------------------/**SHADERINFO The structure is defined in the header file Loadshaders . h, if interested can take a look first, here is not to introduce us first just know 1, for each OpenGL program, when it uses OpenGL version above or equal to 3.1, you need to specify at least two shaders: vertex shader and fragment shader, This task is accomplished by the Loadshaders function below. 2, we need to write an additional two files, for the following example, one is the Triangles.vert vertex shader and the other is the Triangles.frag fragment shader. Two files will be posted at the end of the file. 3, the language used by the shader is OpenGL coloring language GLSL, very similar to C + +. For more information about shaders, the next article is detailed. */shaderinfo shaders[] = {{Gl_vertex_shader, "Triangles.vert"},{gl_fragment_shader, "Triangles.frag"},{GL_NONE, NULL }}; Gluint program = loadshaders (shaders); Gluseprogram,/** function prototype: void Glvertexattribpointer (Gluint index, Glint Size, Glenum type, Glboolean normalized, Glsizei stride, const glvoid* pointer); Before we call the only data that Glbinddata passed to the cache, and then we use it, You must also specify a data type. So the main task of this function is: 1, tell OpenGL, the format of the stored data 2, because we use the shader to program, so in the vertex shader phase, we will use this function to the shader in the type of property variables to pass data. So how do they relate to each other? It is the index of the first parameter that indicates the role of the subscript of the variable in the shader program. Example: Layout (location=index) in Vec4 PositioN If the index is the same as the first parameter of the Glvertexattribpointer, then the data of the relevant buffer will be passed to the position variable. 3, after the function is executed, it will affect the state of changing Vao, VBO will be copied to Vao. Then, if you change the cached object that is currently bound, it will not change to the object in the Vao. */glvertexattribpointer (Vposition, 2, Gl_float, Gl_false, 0, Buffer_offset (0));/** because the array of vertex attributes is inaccessible by default, So we need to invoke the following function to activate it. The range is 0 to Gl_max_vertex_attribs-1*/glenablevertexattribarray (vposition);}
And then we go into the render function display
void display (void) {/** Clears the specified cache data and sets it back to the current purge value parameter to specify multiple numeric parameters by logic or operation. Gl_color_buffer_bit Color Cache gl_depth_buffer_bit Depth Cache gl_stencil_buffer_bit Template cache and OpenGL default clear color is black if you want to specify a different color, Can call Glclearcolor also we need to know that because OpenGL is a state machine, all of its settings OpenGL will be preserved. So for Glclearcolor, the best way to call it is to put it in the initialization method, because it will only be called once if it is placed in display, OpenGL will call it repeatedly set to clear the color value, which can reduce the running efficiency. */glclear (gl_color_buffer_bit);/** The function we have seen in the initialization function, but this time the function is not quite the same before the initialization, is now activated the vertex array object. Now use it as the vertex array used for vertex data. */glbindvertexarray (Vaos[triangles]);/** function prototype void Gldrawarrays (Glenum mode, glint first, Glsizei count), set the render mode to Gl_ Triangles, the starting position is at 0 offset from the cache, rendering numvertices elements altogether. In the future we will continue to learn various elements */gldrawarrays (gl_triangles, 0, numvertices);/** This function forces all the OpenGL commands in progress to be completed immediately and transferred to OpenGL server processing. */glflush ();}
See the time has been more than 11 o'clock in the evening, too late to write parsing shader that part of the code. I will continue to make up here in a couple of days.
2015.07.26
Guangzhou
"OpenGL" second article Hello OpenGL