Learn code address OpenGL(ES) Learn one: Prepare OpenGL(ES) Learn two: Draw a triangle

Two years ago, I started to get started by reading blogs and OpenGL super dictionary. Later, I got into Unity development and had a more intuitive understanding of 3D graphics. I am especially grateful to this book [Unity Shader Introduction Essentials], which gave me a lot of clear knowledge, such as lighting model, normal mapping and so on, which I just understand -_-.

And then recently I started to prepare for explicit and systematic learning of OpenGL, mainly with learnOpenGL. OpenGL’s knowledge, either scattered, or written by foreigners who don’t understand books, is like a super bible, especially in the beginning when a lot of the concepts are not established. This site is really great, step by step. If you can follow learnOpenGL is the best, or Chinese learnOpenGL.

Prepare to write a series of blog posts as study notes, if they can help other learners. Teaching and learning, when thinking of telling a concept to others, will be more clear, rigorous to confirm the concept. Most of the time, some knowledge is in the “it” state in the head, and writing it down makes this understanding clearer.

All the learning codes are in this project, and the tests of win/ MAC /iOS platforms have been done. On iOS, it’s OpenGL ES.

MAC and Windows

1. Need 4 libraries:glfw.glew.soil 和 glm.

  • GLFW is used to open Windows, generate OpenGL context, and access keyboard and mouse control.
  • Glew provides a unified OpenGL interface for each platform. You do not need to perform operations based on the platform
  • Soil is used to load images for texture generation
  • GLM provides the definition and manipulation of 3D variable types such as matrices and vectors. GLM is just a header file, slightly different from the others.

Installation:

1. Use Homebrew to download, except soil, all the others, this is the most convenient. The soil can use [stb_image. H] (https://github.com/nothings/stb/blob/master/stb_image.h) instead. With chocolatey to win, and only GLFW. 2. The web site to download code, in addition to the GLM, several other are compiled into static library to use, and to use cmake (https://cmake.org/download/), because each platform is not the same. Cmake Use the official website to download desktop applications (GLFW and glew), or use the cmake command (soil) on the terminal. The cmake program uses a click on Configure and then Generate to Generate the corresponding program in the target directory. Xcode on MAC, VS on Win, then run the project and compile the static library. After downloading soil, go to the soil root directory and run make & make install to get the static library. 3. Or use the packages compiled in my sample project. 4. Put the static library and corresponding header files into the project.Copy the code

2. Perform initial configuration

Once you’ve built your project, start writing it in the main function.

  • Configuration GLFW

    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, 	GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    Copy the code

    Add to MAC:

    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    Then create the window:

    GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);

    Use the window to build the current context: glfwMakeContextCurrent(window);

    Set the view size of OpenGL. This is the size of the content to be rendered.

    int width,height;
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, width, height);
    Copy the code
  • Initialize GLEW:

    glewExperimental = GLFW_TRUE;
    if(glewInit() ! = GLEW_OK) { std::cout<<"Failed to initilize GLEW" <<std::endl;
        return- 1; }Copy the code
  • Loop through the render command

    while(! glfwWindowShouldClose(window)) { glfwPollEvents(); //Here is render commands glfwSwapBuffers(window); }Copy the code

    GlfwPollEvents handles window events so that the window can respond to the user. GlfwSwapBuffers is a before-and-after buffer, i.e. there are two buffers that store images, one that is currently displayed and the other that is currently being written, so after writing the buffers will be switched so that the newly written buffers are displayed and then another buffer will be rendered. This allows for simultaneous display and writing, which speeds things up.

3. Simple tests

In the render command position add:

GlClearColor (1.0 f, f, 1.0 0.5 f, 1.0 f); glClear(GL_COLOR_BUFFER_BIT);Copy the code

GlClearColor sets the cleared color, and glClear clears the response buffer, using GL_COLOR_BUFFER_BIT.

After running, fill the window with the color you just set, that is, light yellow.

iOS

On iOS, unlike on computers, there is no need for third-party library management Windows, and Apple itself has some packaging on OpenGL ES. Mainly based on Drawing to Other Rendering Destinations.

  1. First of all, you can use GLKit on iOS, which is a packaged tool library for OpenGL ES, but for learning, you don’t use this, you build your own environment.
  2. According to the above documentation, the main is to build their ownFramebufferIt contains information such as the color, depth and template test data needed for a frame. We use the draw command to output data to the Framebuffer, which is then contributed by one of its other componentsCAEAGLLayerThis layer is responsible for displaying.
So follow the documentation:
  1. We need a view to display, so we’re going to create a UIView subclass that encapsulates our OpenGL ES drawing operation. @interface TFGLView: UIView, and then in order for it to render the drawn content, change its layer to CAEAGLLayer.

    Copy the code

+(Class)layerClass{ return [CAEAGLLayer class]; }

2. The initialization EAGLContext ` _context = [[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES3]; 'OpenGL ES3 is used here, so the header file is imported as'#import <OpenGLES/ES3/gl.h>`.Then set the context to the current context: '[EAGLContextsetCurrentContext:_context] '3. Buffers(1, &_frameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer); There are a lot of ``` `glGenxxx functions, which are used to generate something, and half of them are ints, which is just a flag. If you generate a framebuffer, you don't get an object, not even a memory address. _frameBuffer is a 'GLuint' type. You can view them as an ID, and I guess that's all for performance purposes. Write more object-oriented programs, will be a little uncomfortable with this situation. 'glBindxxx' is also a common type used to indicate that the following operations are for bound objects. For example, here and below where 'GL_FRAMEBUFFER' is used, all operations on _frameBuffer are performed until you bind another object again. 4. Build the colorBuffer and attach it to the frameBufferCopy the code

glGenRenderbuffers(1, &_colorBuffer); glBindRenderbuffer(GL_RENDERBUFFER, _colorBuffer); [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_renderLayer]; glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorBuffer);

The first two sentences are the same as the framebuffer. _context is used to share memory between colorbuffer and _renderLayer, so that _renderLayer can display the contents of colorbuffer. Note that GL_RENDERBUFFER is used here, not _colorBuffer, which is what the glBindRenderbuffer binding is for. GLint width,height; glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); glViewport(0, 0, width, height); The glViewport function is also used. GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);if(status ! = GL_FRAMEBUFFER_COMPLETE) { NSLog(@"failed to make complete framebuffer object %x", status); } ` ` `#### Simple drawing

Copy the code

glBindFramebuffer(GL_FRAMEBUFFER, self.frameBuffer); GlClearColor (1.0 f, f, 1.0 0.5 f, 1.0 f); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

GlClearColor sets the clear color, glClear clears the buffer, GL_DEPTH_BUFFER_BIT is the depth buffer, GL_COLOR_BUFFER_BIT is the color buffer. If not, the previous drawing is retained, causing it to be overlaid with the current drawing. Then render the result for display:Copy the code

glBindRenderbuffer(GL_RENDERBUFFER, self.colorBuffer); [self.context presentRenderbuffer:GL_RENDERBUFFER];

Add the custom view to the interface and view the result. If the color is displayed, it is OK.Copy the code