Xcode下搭建OpenGL開發(fā)環(huán)境

Xcode下搭建OpenGL開發(fā)環(huán)境

命令行安裝homebrew

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Homebrew安裝成功后茵瘾,會(huì)自動(dòng)創(chuàng)建目錄 /usr/local/Cellar 來存放Homebrew安裝的程序礼华,可以在finder下點(diǎn)擊shift+command+G進(jìn)入/usr/local/Cellar文件夾

命令行安裝glfw

brew install glfw3

link編譯鏈接(如果已經(jīng)鏈接會(huì)提示W(wǎng)arning)

brew link glfw3

下載glad

http://glad.dav1d.de

將語言(Language)設(shè)置為C/C++,在API選項(xiàng)中拗秘,選擇3.3以上的OpenGL(gl)版本(我們的教程中將使用3.3版本圣絮,但更新的版本也能正常工作)。之后將模式(Profile)設(shè)置為Core聘殖,并且保證生成加載器(Generate a loader)的選項(xiàng)是選中的〕况ǎ現(xiàn)在可以先(暫時(shí))忽略拓展(Extensions)中的內(nèi)容。都選擇完之后奸腺,點(diǎn)擊生成(Generate)按鈕來生成庫文件餐禁。

GLAD現(xiàn)在應(yīng)該提供給你了一個(gè)zip壓縮文件,包含兩個(gè)頭文件目錄突照,和一個(gè)glad.c文件帮非。將兩個(gè)頭文件目錄(gladKHR)復(fù)制到/usr/local/include文件夾中,并添加glad.c文件到你的工程中讹蘑。

添加Custom Paths

在Xcode中找到Peference菜單項(xiàng)末盔,這個(gè)一般在File菜單項(xiàng)左邊的那個(gè)Xcode項(xiàng)目中,然后在里面找到Locations項(xiàng)座慰,再點(diǎn)擊Custom Paths陨舱,添加四項(xiàng)

Name | Display Name | Path
glfw_header | glfw_header | /usr/local/Cellar/glfw3/3.2.1/include
glfw_lib | glfw_lib | /usr/local/Cellar/glfw3/3.2.1/lib

添加Search Path

創(chuàng)建新的Xcode項(xiàng)目(command line tool),語言選擇C++版仔。接著游盲,在項(xiàng)目的Bulid Settings里面找到Header Search Paths和Library Search Paths兩項(xiàng),在Header Search Paths中加入

/usr/local/Cellar/glfw/3.2.1/include

/usr/local/include

Library Search Paths中加入

/usr/local/Cellar/glfw/3.2.1/lib

添加Linked Frameworks

在項(xiàng)目的General中找到Linked Frameworks and Libraries蛮粮,點(diǎn)擊‘+’號(hào)益缎,添加如下兩個(gè)文件

OpenGL.framework
libglfw3.2dylib

添加 libglfw3.2dylib文件的方法是,點(diǎn)擊add other然想,然后點(diǎn)擊shift+command+G進(jìn)入/usr/local/Celler文件夾莺奔,然后根據(jù)我們之前說的安裝glfw3的路徑找到文件

測試代碼

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

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

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";
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";

int main()
{
    // glfw: initialize and configure
    // ------------------------------
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif

    // glfw window creation
    // --------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    // glad: load all OpenGL function pointers
    // ---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }


    // build and compile our shader program
    // ------------------------------------
    // vertex shader
    int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    // check for shader compile errors
    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;
    }
    // fragment shader
    int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    // check for shader compile errors
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // link shaders
    int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    // check for linking errors
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // set up vertex data (and buffer(s)) and configure vertex attributes
    // ------------------------------------------------------------------
    float vertices[] = {
        -0.5f, -0.5f, 0.0f, // left  
         0.5f, -0.5f, 0.0f, // right 
         0.0f,  0.5f, 0.0f  // top   
    }; 

    unsigned int VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
    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(float), (void*)0);
    glEnableVertexAttribArray(0);

    // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
    // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
    glBindVertexArray(0); 


    // uncomment this call to draw in wireframe polygons.
    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // input
        // -----
        processInput(window);

        // render
        // ------
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // draw our first triangle
        glUseProgram(shaderProgram);
        glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
        glDrawArrays(GL_TRIANGLES, 0, 3);
        // glBindVertexArray(0); // no need to unbind it every time 
 
        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // optional: de-allocate all resources once they've outlived their purpose:
    // ------------------------------------------------------------------------
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);

    // glfw: terminate, clearing all previously allocated GLFW resources.
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and 
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
}

運(yùn)行結(jié)果

//一個(gè)橙色的三角形……

Reference

https://blog.csdn.net/longzh_cn/article/details/55001345

https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市变泄,隨后出現(xiàn)的幾起案子令哟,更是在濱河造成了極大的恐慌,老刑警劉巖妨蛹,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屏富,死亡現(xiàn)場離奇詭異,居然都是意外死亡滑燃,警方通過查閱死者的電腦和手機(jī)役听,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人典予,你說我怎么就攤上這事甜滨。” “怎么了瘤袖?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵衣摩,是天一觀的道長。 經(jīng)常有香客問我捂敌,道長艾扮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任占婉,我火速辦了婚禮泡嘴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逆济。我一直安慰自己酌予,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布奖慌。 她就那樣靜靜地躺著抛虫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪简僧。 梳的紋絲不亂的頭發(fā)上建椰,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音岛马,去河邊找鬼棉姐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蛛枚,可吹牛的內(nèi)容都是我干的谅海。 我是一名探鬼主播脸哀,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼蹦浦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了撞蜂?” 一聲冷哼從身側(cè)響起盲镶,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蝌诡,沒想到半個(gè)月后溉贿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浦旱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年宇色,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宣蠕,死狀恐怖例隆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抢蚀,我是刑警寧澤镀层,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站皿曲,受9級(jí)特大地震影響唱逢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜屋休,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一坞古、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧劫樟,春花似錦绸贡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至虑绵,卻和暖如春尿瞭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背翅睛。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工声搁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捕发。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓疏旨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親扎酷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子檐涝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容