【光能蝸牛的圖形學(xué)之旅】Opengl C++ 環(huán)境搭建

本文參考https://learnopengl.com/Getting-started/Creating-a-window

GLFW

GLFW是一個由c寫成的庫,為OpenGL提供基本渲染的的一個實現(xiàn)類庫

Building GLFW

GLFW 的lib庫不一定在每一臺電腦都可以使用蚂夕,所以需要在使用者自己的電腦上編譯GLFW源文件胳喷,以生成lib庫 喂链,這樣是比較靠譜的司草。
下載地址

CMake

CMake是一個工具哥倔,可以使用預(yù)定義的CMake腳本從一組源代碼文件中生成用戶選擇的項目/解決方案文件(例如Visual Studio,Code :: Blocks唯沮,Eclipse)。這使我們可以從GLFW的源代碼包生成一個Visual Studio 2012項目文件堪遂,我們可以使用它來編譯生成GLFW庫介蛉。
下載地址

CMake安裝好后 , 我們將選擇已下載的GLFW源文件包的根文件夾溶褪,然后在GLFW源文件包里面創(chuàng)建一個build文件夾币旧,然后將build輸出目錄選擇這個目錄,具體看如下圖

Image of CMake's logo

一旦設(shè)置了源文件夾和目標(biāo)文件夾猿妈,點擊Configure按鈕吹菱,CMake就可以讀取所需的設(shè)置和源代碼巍虫。然后,我們必須為項目選擇生成器鳍刷,并且由于我們使用的是Visual Studio 2017占遥,因此我們將選擇“Visual Studio 17” 。然后CMake將顯示可能的構(gòu)建選項來配置結(jié)果庫输瓜。這個時候不用管瓦胎,再次點擊`Configure就可以存儲設(shè)置完成 ,然后接著我們可以點擊Generate尤揣,生成的項目文件會在你的build文件夾中生成搔啊。

Compilation

在build文件夾中,可以找到一個名為GLFW.sln的文件北戏,并且我們用Visual Studio 2017打開它负芋。
我們可以點擊Build Solution按鈕,然后會在build / src / Debug生成的編譯庫glfw3.lib (注意最欠,我們使用的是版本3)示罗。

GLFW源代碼目錄中,你會看到由一個Include目錄芝硬,然后里面是GLFW的一些庫文件蚜点,這個Include庫文件以及之前說過的glfw3.lib 是我們所需要的。

Glad

在完成準(zhǔn)備工作之前拌阴,由于OpenGL是一個標(biāo)準(zhǔn)/規(guī)范绍绘,因此驅(qū)動程序制造商必須將該規(guī)范實施到特定圖形卡支持的驅(qū)動程序。由于OpenGL驅(qū)動程序有許多不同的版本迟赃,其大部分功能的位置在編譯時并不知道陪拘,需要在運行時查詢。然后開發(fā)人員的任務(wù)是檢索他/她所需功能的位置并將它們存儲在函數(shù)指針中以備后用纤壁。檢索這些位置是特定于操作系統(tǒng)的左刽,在Windows中它看起來像這樣:

//定義函數(shù)的原型
typedef void(* GL_GENBUFFERS)(GLsizei,GLuint *);
//找到函數(shù)并將其分配給函數(shù)指針
GL_GENBUFFERS glGenBuffers =(GL_GENBUFFERS)wglGetProcAddress(“glGenBuffers”);
//現(xiàn)在可以調(diào)用正常的函數(shù)
無符號整型緩沖區(qū);
glGenBuffers(1酌媒,&buffer);

正如你所看到的欠痴,代碼看起來很復(fù)雜,對于你可能需要的尚未聲明的每個函數(shù)來說秒咨,這是一個麻煩的過程喇辽。值得慶幸的是,這里還有一些專門處理這類事務(wù)的類庫Glad

設(shè)置GLAD

GLAD是一個 開源的庫雨席, 下載地址菩咨,可以管理我們所討論的所有繁瑣工作。 GLAD與大多數(shù)常見的開源庫有略微不同的配置設(shè)置。 GLAD使用Web服務(wù)抽米,我們可以告訴GLAD我們要定義哪個版本的OpenGL特占,并根據(jù)該版本加載所有相關(guān)的OpenGL函數(shù)。所以一般我們不用關(guān)心這個源代碼缨硝,只需要使用由這個開源庫提供的Web服務(wù)即可

我們打開 Web服務(wù) (點擊這個鏈接)摩钙,將會打開一個網(wǎng)頁,在網(wǎng)頁中做如下操作:
確保語言設(shè)置為C ++查辩,
并在API部分中選擇至少3.3的OpenGL版本(這是我們將用于這些教程的內(nèi)容;更高版本也可以)胖笛。
確保配置文件設(shè)置為Core,
保證Generate a loader被勾選宜岛。忽略擴展(至少在目前為止我們先這么做)长踊,
然后單擊generate以生成庫文件。

然后你可以看到GLAD應(yīng)該已經(jīng)為您提供了一個zip文件萍倡,其中包含兩個包含文件夾glad and KHR和一個glad.c文件身弊。這幾個東西是我們需要的。

準(zhǔn)備

1.在你的工作目錄新建一個目錄Opengl
2.在Opengl里面新建兩個文件夾IncludesLibs
3.將前文提到的GLFW的Include文件里的glfw目錄glad ,KHR 均拷貝到Includes目錄下
4.將前文提到的GLFW的glfw3.lib拷貝到Libs目錄下
5.glad.c將會拷貝到vs工程列敲,這個后面交代

微信截圖_20180419205046.png

微信截圖_20180419205105.png

Our first project

現(xiàn)在讓我們打開Visual Studio并創(chuàng)建一個新項目阱佛。如果給出多個選項并選擇空項目,請選擇Visual C ++(不要忘記給項目一個合適的名稱)戴而。我們現(xiàn)在有一個工作空間來創(chuàng)建我們的第一個OpenGL應(yīng)用程序凑术!

我們將glad.c拷貝到工程目錄源代碼目錄,同時新建一個Main.cpp文件所意,并粘貼如下內(nèi)容

#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);
}

Linking

在跑起來之前淮逊,還有一些東西需要設(shè)置

通過轉(zhuǎn)到項目屬性(在解決方案資源管理器中右鍵單擊項目名稱),我們可以添加這些目錄(其中VS應(yīng)該搜索庫/包含文件)扶踊,然后轉(zhuǎn)到“VC ++目錄”泄鹏,如圖中所示下面(請注意圖中加粗的部分),用于配置類庫和引用:

微信截圖_20180419210231.png

然后是鏈接器輸入配置秧耗,如下


微信截圖_20180419210413.png

之后备籽,你build工程,就可以看到一個三角形分井,如下圖

微信截圖_20180419210636.png

本文是一個簡化版本胶台,詳細版本,請參見https://learnopengl.com/Getting-started/Creating-a-window
Have Fun杂抽。

其他后續(xù)問題

今天發(fā)現(xiàn)opengl開源庫有很多版本,比如glut韩脏,freeGlut等等缩麸,相應(yīng)的配置方式可以參考各自的官方鏈接,如有需要赡矢,后期補上這方面的配置說明

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末杭朱,一起剝皮案震驚了整個濱河市阅仔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌弧械,老刑警劉巖八酒,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異刃唐,居然都是意外死亡羞迷,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門画饥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衔瓮,“玉大人,你說我怎么就攤上這事抖甘∪劝埃” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵衔彻,是天一觀的道長薇宠。 經(jīng)常有香客問我,道長艰额,這世上最難降的妖魔是什么澄港? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮悴晰,結(jié)果婚禮上慢睡,老公的妹妹穿的比我還像新娘。我一直安慰自己铡溪,他們只是感情好漂辐,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棕硫,像睡著了一般髓涯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哈扮,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天纬纪,我揣著相機與錄音,去河邊找鬼滑肉。 笑死包各,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的靶庙。 我是一名探鬼主播问畅,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了护姆?” 一聲冷哼從身側(cè)響起矾端,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卵皂,沒想到半個月后秩铆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡灯变,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年殴玛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柒凉。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡族阅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出膝捞,到底是詐尸還是另有隱情坦刀,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布蔬咬,位于F島的核電站鲤遥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏林艘。R本人自食惡果不足惜盖奈,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望狐援。 院中可真熱鬧钢坦,春花似錦、人聲如沸啥酱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镶殷。三九已至禾酱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绘趋,已是汗流浹背颤陶。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留陷遮,地道東北人滓走。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像帽馋,于是被迫代替她去往敵國和親搅方。 傳聞我的和親對象是個殘疾皇子疫粥,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

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