The premise to prepare

Before we can open Xcode, we need to prepare two libraries: GLFW and GLAD. These are the libraries you’ll need to rely on to develop OpenGL, so let’s take a look at how to prepare them:

GLFW

Before we can draw any effects, the first thing we need to do is create an OpenGL context and a window for display. However, these operations are different on every system, and OpenGL purposefully abstracts them away. This means we have to deal with creating Windows, defining OpenGL contexts, and handling user input ourselves.

Fortunately, several libraries already provide the functionality we need, some of which are OpenGL specific. These libraries save us time writing operating system-specific code and provide us with a window and context for rendering. Some of the most popular are GLUT, SDL, SFML, and GLFW.

Now let’s download this library from GLFW: www.glfw.org/download.ht…

You can either download the source code to compile it, or download the pre-compiled version directly. Here, for convenience, I will directly download the macOS precompiled library:

Once the download is complete, unzip it and open it. We need these things:

  • Compile the generated library
  • The include file

The contents of the following two folders:

We will see how to use these folders later. Now that GLFW is ready, let’s prepare the GLAD library.

GLAD

Since OpenGL is only a standard/specification, the implementation is up to the driver developer for a specific graphics card. Due to the large number of OpenGL driver versions, the positions of most of its functions cannot be determined at compile time and need to be queried at run time. So it falls to the developer to retrieve the function address at runtime and store it in a function pointer for later use. Such code is very complex and tedious, and we need to repeat the process for every possible function. Fortunately, GLAD this library can help us do these things.

Go to the official website of GLAD: GLAD. Dav1d. de/

Set the Language to C/C++, select the OpenGL version 3.3 in the API options, then set the Profile to Core and make sure the Generate a loader option is checked. You can ignore the content in Extensions for now (for now). Once you’ve selected them, click Generate to Generate the library file:

After the download is complete, there will be two folders, which will be used later:Now that we’re ready, we need to open Xcode for configuration.

Open the Xcode

Creating a new project

Now create a new Xcode project and select the console application:

Just fill in the blanks for the next step, my language will be C++ :

Adding dependencies

Add header files to search roadways

First, we need to add the header file to the project:This is set toxcodeproj -> Build Settings -> Search Paths -> Header Search PathsHere we need to add the headers of the two libraries we just downloaded, namely the unzipped include folder.

Add the glad. C file

Secondly, remember that there is a SRC folder in glad after downloading and we need to add the glad. C file to the project:

Add dependent libraries such as GLFW

Then, we need to add the GLFW library file, and add the other libraries:

The directory is xcodeproj -> Build Phases -> Link Binary With Libraries. This one needs to be introduced as an add File, and the others need to be introduced as well, so you can find them by searching.

Add library files to search roadways

Finally, you need to add a search path for library files, otherwise Xcode won’t find libglfw3.a. Adding this path is the same as adding a header search path. This setting is set inxcodeproj -> Build Settings -> Search Paths -> Library Search Paths:

With these few steps, you are now ready to draw using OpenGL. So let’s draw a triangle.

Once configured, draw a triangle

Drawing a triangle through OpenGL is not an easy task. Not only do you have to call GLFW to create an OpenGL context, you also have to compile shaders, build renderers, deal with vertex array objects, and so on. This can’t be said in a moment, so I’ll say more here.

Finally, attach a program and copy it to Xcode’smain.cppXcode’s OpenGL environment is configured successfully if a triangle can be found. The final result is as follows:

The code is as follows:

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0.0, width, height);
}


int main(int argc, const char * argv[]) {
    
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    
    GLFWwindow* window = glfwCreateWindow(800.600."example".NULL.NULL);
    if (window == NULL)
    {
        std: :cout << "Failed to create GLFW window" << std: :endl;
        glfwTerminate();
        return - 1;
    }
    glfwMakeContextCurrent(window);
    
    if(! gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {std: :cout << "Failed to initialize GLAD" << std: :endl;
        return - 1;
    }

    glViewport(0.0.800.600);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    
    const char *vertexShaderSource = "#version 330 core\n"
        "layout (location = 0) in vec3 aPos; \n"
        "void main()\n"
        "{\n"
        "Gl_Position = vec4(apos. x, apos. y, apos. z, 1.0); \n"
        "} \ 0";
    
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if(! success) { glGetShaderInfoLog(vertexShader,512.NULL, infoLog);
        std: :cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std: :endl;
    }
    
    const char *fragmentShaderSource = "#version 330 core\n"
        "out vec4 FragColor; \n"
        "void main()\n"
        "{\n"
        "FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f); \n"
        "}\n\0";
    
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if(! success) { glGetShaderInfoLog(fragmentShader,512.NULL, infoLog);
        std: :cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std: :endl;
    }
    
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if(! success) { glGetProgramInfoLog(shaderProgram,512.NULL, infoLog);
        std: :cout << "ERROR::PROGRAM::LINK_FAILED\n" << infoLog << std: :endl;
    }
    
    glUseProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    
    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);
    
    float vertices[] = {
        0.5 f.0.5 f.0.0 f.0.5 f.0.5 f.0.0 f.0.0 f.0.5 f.0.0 f
    };
    
    unsigned int VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    glVertexAttribPointer(0.3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    
    glClearColor(0.2 f.0.3 f.0.3 f.1.0 f);
    
    while(! glfwWindowShouldClose(window)) { glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES,0.3);
        
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    
    glfwTerminate();
    return 0;
}

Copy the code