Computer graphics & the configuration of OpenGL environment

(from the original author) Source , reprint please keep the information)

Preface

                      OpenGL As a graphics rendering engine, and using freeglut Create window, handle keyboard, mouse input, etc. It covers everything from the configuration of the OpenGL environment to the creation of a simple 3D scene with lights. Compared with the previous professional courses such as web basic training and introduction to computational thinking, the course of computer graphics has a higher entry threshold, which requires some knowledge of space analytic geometry and linear algebra in advanced mathematics; for the same course without graphic programming or image processing foundation, there are many new concepts that need to be understood and mastered; the program code is large, which requires one The ability of coding; in addition to all kinds of comments about demonizing the course heard by students from the elders and sisters; therefore, I have a course for this course, which is equipped with relevant codes and Visual studio engineering; at the same time, it is also the work of the director of the Information Department of the College Association for science and technology. At the same time, because only for the course, there will be a lot of related computer graphics content missing, interested students can learn more by themselves.

If you want to reprint this tutorial, please keep the source.

What is computer graphics

In short, the main research content of computer graphics is to study the principles and algorithms of how to represent graphics in computer, and how to use computer to calculate, process and display graphics. A graph is usually composed of geometric elements such as points, lines, faces, and bodies, and non geometric attributes such as grayscale, color, linetype, and lineweight. In terms of processing technology, graphics are mainly divided into two categories: one is based on line information representation, such as engineering drawing, contour map, curve block diagram of surface, and the other is light and dark map, which is commonly referred to as realistic graphics.

One of the main purposes of computer graphics is to make use of computers to produce realistic graphics. Therefore, it is necessary to create a geometric representation of the scene described by the graphics, and then calculate the lighting effect under the imaginary light source, texture and material attributes by using a certain lighting model. So computer graphics is closely related to another subject, computer aided geometric design. In fact, graphics also takes the curve and surface modeling technology and solid modeling technology which can represent geometric scene as its main research content. At the same time, the result of realistic graphics calculation is provided by digital image, and computer graphics is closely related to image processing.

The difference between the two concepts of figure and image is more and more blurred, but there is still a difference: image only refers to the gray information in the form of bitmap in the computer, while figure contains geometric attributes, or more emphasis on the geometric representation of the scene, which is composed of the geometric model of the scene and the physical attributes of the scene.

The research content of computer graphics is very extensive, such as graphics hardware, graphics standards, graphics interaction technology, raster graphics generation algorithm, curve and surface modeling, solid modeling, realistic graphics calculation and display algorithm, non realistic rendering, as well as calculation visualization, computer animation, natural scenery simulation, virtual reality, etc.

(from wikipedia for more information Here)

What is OpenGL


OpenGL (full name: Open Graphics Library) is a cross language and cross platform application programming interface (API) for rendering 2D and 3D vector graphics. This interface is composed of nearly 350 different function calls. It is used to draw complex 3D scenes from simple graphics bits. It is often used in CAD, virtual reality, scientific visualization programs and video game development.

   the OpenGL specification is maintained by the OpenGL architecture review board (ARB) established in 1992. ARB consists of companies that are particularly interested in creating a unified, universally available API. According to the official website of OpenGL, the voting members of ARB in June 2002 include 3Dlabs, Apple Computer, ATI Technologies, Dell Computer, Evans & Sutherland, Hewlett Packard, IBM, Intel, Matrox, NVIDIA, SGI and Sun Microsystems. Microsoft was one of the founding members, but withdrew in March 2003.

(the above is from wikipedia, more information can be found in Here)

    this tutorial will use OpenGL4.0, mainly using Visual studio on Windows platform, with two third-party libraries of freePlug and glew (no glm math library is used, because the related math is the content of the exam, so the tutorial will realize the required math function by itself), and use the programmable rendering pipeline to realize the drawing of a fractal triangle. The effect is as follows: Figure:


It is said that the most troublesome problem of computer graphics course is to configure an environment that can compile and run OpenGL applications. It's said that some students failed to set up the environment from the beginning to the end of the course. If you ask the TA for help, they will let you install a VS2013 first. As mentioned earlier, this tutorial uses two third-party libraries, freePlug and glew. FreePlug is a library used to create windows that support opengl rendering and can handle input such as keyboard and mouse, and it is quite simple to use (compared with directly using Windows API to create OpenGL device context and render context, or other similar libraries such as glfw). Glew is a library that allows you to use modern OpenGL features (because Microsoft has its own product Direct3D and OpenGL are competitors, the OpenGL API of windows system only supports OpenGL 1.1, in order to use the updated OpenGL, glew is required).

I have packed and integrated the files of freePlug and glew. You can go to Baidu SkyDrive Download, extract code: ed1h. Install them in your Visual studio (this method is applicable to vs201520172019 and above):

  • Unzip OpenGLENV.zip downloaded from the online disk, and after entering, you can see these three folders:
  • Find the installation path of Windows Development Kits, usually under C:\Program Files (x86)\Windows Kits
  • If your computer is a Windows 10 system, you will see a folder called "10" in it and enter:

  • Next, select all header files in the subfolder include folder of OpenGLENV folder and copy them
  • Then paste it into the folder C:\Program Files (x86)\Windows Kits\Include.0.18362.0\um\gl (note the path, the number of the folder under the Include folder represents windows 10 Your SDK version may not be 18362, but something else. If there are multiple versions, you should choose the one with the largest version number, but to be sure, you can do the following for each one.)
  • This completes the installation of the header file

  • Next, install the library file
  • Enter the lib folder under OpenGLENV, which contains two subfolders, x86 and x64, corresponding to the 32-bit version and 64 bit version of the library files respectively


    Select two. Lib files in the x86 folder, copy and paste them into C:\Program Files (x86)\Windows Kits\Lib.0.18362.0\um\x86, select two. Lib files in the x64 folder, copy and paste them into C: \ program files (x86) \ windows Kit \ 10 \ lib \ 10.0.18362.0 \ um \ x64 (note the path, as mentioned before, your version number may be different from mine, if there are multiple versions, you can install them in multiple versions). Then the installation of the library file is completed

  • Installation of runtime

  • Enter the bin folder under OpenGLEnv. There are two subfolders, System32 and SysWOW64, which distribute the corresponding 64 bit and 32-bit runtime dynamic link libraries (yes, not reversed). Copy and paste the two. dll files in the system 32 subfolder into C:\Windows\System32, and copy and paste the two. dll files in the SysWOW64 subfolder into the C:\Windows\SysWOW64 folder. This completes the installation of the runtime.

    Now that the OpenGL development environment is installed, you can try to create some new C + + projects and add the following code (or download the FirstOpenGL project)

    At this stage, you don't need to understand the meaning of the code. It's just to test whether your OpenGL environment has been successfully installed. The code intentionally uses the features of modern OpenGL to realize it. If the code can be compiled and run smoothly and see the golden fractal triangle, congratulations. You can officially start the study of computer graphics and OpenGL. This tutorial will try to use the source code form of such a single file all the time, which is easy to hand in homework

    #include <Windows.h>   //This header file should be before the opengl header file
    #include <gl/glew.h>   //This header file should be before other opengl header files
    #include <gl/glut.h>
    #include <utility>
    #include <string>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    #include <ctime>
    #include <cstdlib>
    
    #define makeString(x) #x
    #pragma comment(lib, "opengl32.lib")
    #pragma comment(lib, "freeglut.lib")
    #ifdef _WIN64   //If compiling a 64 bit program
    #pragma comment(lib, "glew64.lib")
    #else 
    #pragma comment(lib, "glew32.lib")
    #endif
    //Width and height of picture (pixels)
    constexpr int viewWidth = 800;
    constexpr int viewHeight = 800; 
    
    class GLProgram
    {
        union {
            struct {
                GLuint vshader, fshader;
            }shaders;
            GLuint shadersByIndex[sizeof(shaders) / sizeof(GLuint)];
        };
        constexpr static int shadersGLTable[] = {GL_VERTEX_SHADER, GL_FRAGMENT_SHADER};
        
        GLuint program;
    
        void createShader(const std::string& code, int index) {
            const GLchar* codea[1] = { code.c_str() };
            GLuint& shader = shadersByIndex[index];
    
            shader = glCreateShader(shadersGLTable[index]);
            if (!shader)
                throw std::runtime_error("Can not create shader(glCreateShader)");
            glShaderSource(shader, 1, codea, nullptr);
            glCompileShader(shader);
            GLint res;
            glGetShaderiv(shader, GL_COMPILE_STATUS, &res);
            if (res == GL_FALSE) {
                GLint len;
                glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
                if (len > 0) {
                    std::string info;
                    info.resize(len + 1);
                    int w;
                    glGetShaderInfoLog(shader, len, &w, (GLchar*)(info.c_str()));
                    info[w] = 0;
                    throw std::runtime_error("Shader compilation error:" + info);
                }
            }
        }
    
    public:
        constexpr static int INDEX_VERTEX_SHADER = 0;
        constexpr static int INDEX_FRAGMENT_SHADER = 1;
    
        GLProgram() {
            memset(&shaders, 0, sizeof(shaders));
            program = 0;
        }
        ~GLProgram() {
            if (shaders.vshader)
                glDeleteShader(shaders.vshader);
            if (shaders.fshader)
                glDeleteShader(shaders.fshader);
            if (program)
                glDeleteProgram(program);
        }
    
        void createVShader(const std::string& code) {
            createShader(code, INDEX_VERTEX_SHADER);
        }
        void createFShader(const std::string& code) {
            createShader(code, INDEX_FRAGMENT_SHADER);
        }
        void createProgram() {
            program = glCreateProgram();
            if (!program)
                throw std::runtime_error("Fail to create opengl program(glCreateProgram)");
            glAttachShader(program, shaders.vshader);
            glAttachShader(program, shaders.fshader);
            glLinkProgram(program);
            GLint res;
            glGetProgramiv(program, GL_LINK_STATUS, &res);
            if (res == GL_FALSE) {
                GLint len;
                glGetProgramiv(shaders.fshader, GL_INFO_LOG_LENGTH, &len);
                if (len > 0) {
                    std::string info;
                    info.resize(len + 1);
                    int w;
                    glGetProgramInfoLog(shaders.fshader, len, &w, (GLchar*)(info.c_str()));
                    info[w] = 0;
                    throw std::runtime_error("Fail to link opengl program:" + info);
                }
            }
        }
        void useProgram() const {
            if (!program) {
                throw std::runtime_error("Trying to use an invalid opengl program");
            }
            glUseProgram(program);
        }
        GLuint getProgram() const { return program; }
        operator GLuint() const {  //Function called when object is cast to fluent
            return program;
        }
        operator int() const { return program; }
    };
    
    //Initialize OpenGL
    void initGL() {
        GLenum err = glewInit();
        if (err != GLEW_OK) {
            MessageBox(0, TEXT("Initialization GLEW fail"), TEXT("error"), 0);
            exit(1);
        }
        if (!GLEW_VERSION_4_0) {  //Check OpenGL 4.0 support
            MessageBox(0, TEXT("This computer does not support OpenGL4.0"), TEXT("error"), 0);
            exit(1);
        }
        glEnable(GL_FRAMEBUFFER_SRGB); //Enable gamma correction
    }
    
    struct Point {
        float x, y;
        Point middle(const Point& p) const {  //Midpoint with another point
            return Point{ (x + p.x) / 2, (y + p.y) / 2 };
        }
    };
    struct Triangle {
        Point points[3];
    };
    struct Color {
        float r, g, b, a;
    };
    
    
    //Here is the code of vertex shader and fragment shader. The function is very basic, just to test whether the function of shader is normal
    static const char* vertexShaderCode = makeString(
    #version 400\n
    layout(location = 0) in vec2 pos;
    out vec4 vo_pos;
    void main() {
        gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
    }
    );
    
    static const char* fragmentShaderCode = makeString(
    #version 400\n
    uniform vec4 color;
    void main() {
        gl_FragColor = color;
    }
    );
    
    class RenderState {
        unsigned long long tick;   //Chronograph
        //TODO: define the resources needed for drawing here
        GLProgram program;
        constexpr static int MAX_DEPTH = 9;
        GLuint VAO, VBO;
    
        //Work of updating logical data of each frame
        void update() {
            tick++;
        }
    public:
        RenderState() {
            tick = 0;
        }
      
        //Work before first drawing
        void preScene() {
            printf("PreScene");
            program.createVShader(vertexShaderCode);
            program.createFShader(fragmentShaderCode);
            program.createProgram();
            program.useProgram();
    
            //Here create a VAO and VBO to store three vertices of a triangle
            glGenVertexArrays(1, &VAO);
            glGenBuffers(1, &VBO);
            glBindVertexArray(VAO);
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glVertexAttribPointer(0, 2, GL_FLOAT, true, 2 * sizeof(float), nullptr);
            glEnableVertexAttribArray(0);
            //In fact, you should call glDeleteBuffer to destroy resources after drawing... However, when the glut window is closed, you will exit directly, and there is no chance to destroy resources
            //That's it
        }
     
        void recursiveDraw(const Triangle& tr, int depth = 0) {
            if (depth == MAX_DEPTH) 
                return;
    
            //Update vertex buffer data: change vertex data to three vertices of the current triangle
            glBufferData(GL_ARRAY_BUFFER, sizeof(tr), &tr, GL_DYNAMIC_DRAW);
           
            glUniform4f(glGetUniformLocation(program, "color"), 0.88, 0.76, 0.42, 1.0);  //Golden
            glDrawArrays(GL_TRIANGLES, 0, 3);  
      
            //Hollowing out the middle
            Point m1 = tr.points[0].middle(tr.points[1]);
            Point m2 = tr.points[0].middle(tr.points[2]);
            Point m3 = tr.points[1].middle(tr.points[2]);
            Triangle m = { m1, m3, m2 };  //A triangle formed by the midpoint of three sides
            glBufferData(GL_ARRAY_BUFFER, sizeof(m), &m, GL_DYNAMIC_DRAW);
            glUniform4f(glGetUniformLocation(program, "color"), 0.0, 0.0, 0.0, 0.0);
            glDrawArrays(GL_TRIANGLES, 0, 3);
    
            //Draw the next layer:
            recursiveDraw(Triangle{ tr.points[0], m1, m2 }, depth + 1);
            recursiveDraw(Triangle{ m1, tr.points[1], m3 }, depth + 1);
            recursiveDraw(Triangle{ m2, m3, tr.points[2] }, depth + 1);
        }
        //The work of drawing each frame
        void render() {
            update(); //Update logic first, then render
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            glClearColor(0.0f, 0.0f, 0.0f, 0.0f);  //Set transparent color as background color
    
            recursiveDraw(Triangle{ Point{0.0, 0.882}, Point{-1.0, -0.85}, Point{1.0, -0.85} });
    
            glutSwapBuffers();
            glutPostRedisplay();
        }
    
    }state;
    
    void render() {
        state.render();
    }
    
    int main(int argc, char* argv[]) {
        srand(time(NULL));
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);   //RGBA color mode, double buffering
        glutInitWindowSize(viewWidth, viewHeight);    //Width and height of window
        glutCreateWindow("OpenGL Demo");
        //Note that the following two lines of code must be placed after the glutCreateWindow, otherwise it will fail because the opengl context is not created.
        glViewport(0, 0, viewWidth, viewHeight);
        initGL();  
        state.preScene();
        glutDisplayFunc(render);
        
        glutMainLoop();
        return 0;
    }
    

    Self test questions & Enlightenment

  • What is computer graphics
  • The method of installing freePlug and glew in the previous section is also applicable to installing any other library. Try to master
  • Published 30 original articles, won praise 18, visited 50000+
    Private letter follow

    Keywords: Windows Programming SDK Fragment

    Added by env-justin on Sun, 02 Feb 2020 14:40:03 +0200