在macOS上学习OpenGL | 环境配置并绘制三角形

数据科学与计算机学院 徐海洋

本学习基于 LearnOpenGL (旧版)。

基本环境:

  • MacBook Pro (15-inch, 2016)
  • macOS High Sierra (版本10.13.3)
  • Inter HD Graphics 530 1536 MB
  • Xcode (Version 9.2)

使用 GLUT 的方法:

  1. 在 Xcode 项目配置里的 Build Phases 中添加库 OpenGL.frameworkGLUT.framework
  2. 在源文件中引入头文件 GLUT.h

⚠️:在 Xcode 中警告使用的 glut 函数在 macOS 10.9 开始被弃用。

解决办法为:在 Xcode 项目配置里的 General 中修改部署目标为 10.8 或以下版本。

⚠️:系统默认的 OpenGL 的实现版本为 2.1

查看 OpenGL 版本等信息的办法为:

// 在初始化及创建窗口后
std::cout << "OpenGL Vendor: " << glGetString(GL_VENDOR) << std::endl;
std::cout << "OpenGL Renderer: " << glGetString(GL_RENDERER) << std::endl;
std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl;

在学习中要求使用 OpenGL 版本为 3.3 及以上

首先,在 Apple 的开发者网站 OpenGL for macOS 中查看设备的 OpenGL 版本支持。(本设备支持 4.1 版本)

接下来,采用 GLEWGLFW 的解决方案,一个较好的实践为:

  • 安装 GLEW:从其 GitHub 中下载 zip 解压后进入根目录。
$ make
$ sudo make install
$ make clean

⚠️:在本机实践中需要先在 auto 文件夹中 make 一下。

  • 安装 GLFW:首先在 CMake 官网 中下载 dmg 文件并安装;接着在 GLFW 的 GitHub 仓库中下载 zip 并解压;最后使用 CMake 编译源文件。

在macOS上学习OpenGL | 环境配置并绘制三角形_第1张图片

⚠️:在本机实践中先 configure 后勾选 BUILD_SHARED_LIBS 来创建库,再 configure 一次后点击 Generate 并确认完成。

  • 配置 Xcode 项目: 同样地,先在 Build Phases 中添加库 libGLEW.2.1.0.dyliblibglfw.3.3.dylib 。不同的是,在 Build Settings 中分别设置 Always Search User PathsYes , Header Search Paths/usr/local/includeLibrary Search Paths/usr/local/lib

在macOS上学习OpenGL | 环境配置并绘制三角形_第2张图片

在macOS上学习OpenGL | 环境配置并绘制三角形_第3张图片

完成配置后,在源文件中依次引入头文件 glew.h 和 glfw3.h 并添加代码段:

// 在 glfw 初始化后
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);  // for Mac OS X

⚠️:确认安装最新的 glfw 版本并完成上述代码配置,因为在 3.2 版本下本机实践出现了 first responder error

最后,根据教程中绘制三角形的方法(着色器、VBO 和 VAO),成功在本机上使用 OpenGL 4.1 复现 。

⚠️:可能出现创建的窗口红色闪烁问题,在本机实践中利用清除颜色可以解决。
⚠️:可能出现其他绘制方法没有显示的问题,建议使用教程方法解决。
⚠️:教程中的 glfwGetFramebufferSize 函数可能无法使用,利用文中的可选方案解决。
⚠️:教程参考代码。

复现代码如下:

//
//  main.cpp
//  opengl
//
//  Created by hay on 2018/3/6.
//  Copyright © 2018年 hay. All rights reserved.
//

#include 

// GLEW
#define GLEW_STATIC
#include 

// GLFW
#include 


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

int main() {

    glfwInit();

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);  // for Mac OS X

    GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGLab", nullptr, nullptr);
    if (window == nullptr) {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    glewExperimental = GL_TRUE;
    if (glewInit() != GLEW_OK) {
        std::cout << "Failed to initialize GLEW" << std::endl;
        return -1;
    }

    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);  // glfwGetFramebufferSize doesnt work

    GLfloat vertices[] = {
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };

    GLuint VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // Vertex Shader
    char* vertexShaderSource = "#version 330 core\n\nlayout (location = 0) in vec3 position;\n\nvoid main()\n{\n\tgl_Position = vec4(position.x, position.y, position.z, 1.0);\n}";

    GLuint vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);

    GLint success;
    GLchar 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;
    }

    // Fragment Shader
    char* fragmentShaderSource = "#version 330 core\n\nout vec4 color;\n\nvoid main()\n{\n\tcolor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n}";
    GLuint 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;
    }

    GLuint 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::SHADER::PROGRAM::LINK_FAILED\n" << infoLog << std::endl;
    }

    glUseProgram(shaderProgram);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);


    GLuint VAO;
    glGenVertexArrays(1, &VAO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    glBindVertexArray(0);


    std::cout << "OpenGL Vendor: " << glGetString(GL_VENDOR) << std::endl;
    std::cout << "OpenGL Renderer: " << glGetString(GL_RENDERER) << std::endl;
    std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl;
    std::cout << "GLFW library version: " << glfwGetVersionString() << std::endl;


    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glBindVertexArray(0);

        glfwSwapBuffers(window);
    }

    glfwTerminate();
    return 0;

}


你可能感兴趣的:(计算机图形学)