程式碼 main.cpp
#include <iostream> #include <glad/glad.h> #include <glfw3.h> #include <math.h> using namespace std; // 回撥函式,每當視窗改變大小,視口大小也跟隨改變 void framebuffer_size_callback(GLFWwindow* window,int width,int height) { glViewport(0,0,width,height); } // 輸入 在GLFW中實現一些輸入控制 void processInput(GLFWwindow *window) { if(glfwGetKey(window,GLFW_KEY_ESCAPE) == GLFW_PRESS) // 是否按下了返回鍵(Esc) { glfwSetWindowShouldClose(window,true); // 把WindowShouldClose屬性設定為 true來關閉GLFW } } // ************** opengl 具體實現 ************ // 頂點資料 float vertices[] = { // 位置 // 顏色 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右下 -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左下 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 頂部 }; // 頂點著色器原始碼 const char *vertexShderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" // 位置變數的屬性位置值為 0 "layout (location = 1) in vec3 aColor;\n" // 顏色變數的屬性位置值為 1 "out vec3 ourColor;" // 向片段著色器輸出一個顏色 "void main()\n" "{\n" " gl_Position = vec4(aPos,1.0);\n" // 把一個vec3作為vec4的構造器的引數 " ourColor = aColor;\n" // 將ourColor設定為我們從頂點資料那裡得到的輸入顏色 "}\0"; // 片段著色器原始碼 const char *fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "in vec3 ourColor;\n" // 從頂點著色器傳來的輸入變數(名稱相同、型別相同) "void main()\n" "{\n" " FragColor = vec4(ourColor,1.0);\n" "}\0"; //****************************************** int main() { cout << "shaders" << endl; // GLFW (視窗) glfwInit(); // 初始化GLFW 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); Mac OS X系統 // 建立一個GLFW視窗物件 GLFWwindow* window = glfwCreateWindow(800,600,"shaders",NULL,NULL); if(window == NULL) { std::cout<< "Failed to create GLFW window"<<std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); // 視窗的上下文設定為當前執行緒的主上下文 // GLAD if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) // 初始化GLAD(初始化OpenGL函式指標) { std::cout<<"Failed to initialize GLAD"<<std::endl; return -1; } //*********** opengl 具體實現 ****************** // 頂點陣列物件 VAO unsigned int VAO; glGenVertexArrays(1,&VAO); // 建立頂點陣列物件 glBindVertexArray(VAO); // 繫結頂點陣列物件 // 頂點緩衝物件 VBO unsigned int VBO; glGenBuffers(1,&VBO); glBindBuffer(GL_ARRAY_BUFFER,VBO); // 繫結頂點緩衝物件 glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW); // 把之前定義的頂點資料複製到緩衝的記憶體中 // 頂點著色器物件 unsigned int vertexShader; vertexShader = glCreateShader(GL_VERTEX_SHADER); // 建立頂點著色器物件 glShaderSource(vertexShader,1,&vertexShderSource,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; } // 片段著色器物件 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::vertex::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); } // 把著色器物件連結到程式物件以後,刪除著色器物件 glDeleteShader(vertexShader); glDeleteShader(fragmentShader); // 使用著色器程式物件 glUseProgram(shaderProgram); // 位置屬性 0 來自頂點著色器的location = 0 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // 顏色屬性 1 來自頂點著色器的location = 1 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float))); glEnableVertexAttribArray(1); //************************** // 視口 glViewport(0,0,800,600); // 視口跟隨視窗大小改變 glfwSetFramebufferSizeCallback(window,framebuffer_size_callback); // 渲染迴圈 while(!glfwWindowShouldClose(window)) // 檢查GLFW是否被要求退出 { // 輸入 (使用者) processInput(window); // 輸入控制(自定義) //************** 渲染指令 (使用者)********** glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shaderProgram); float timeValue = glfwGetTime(); float greenValue = (sin(timeValue) / 2.0f) + 0.5f; int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor"); glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES,0,3); //*************************************** // 檢查並呼叫事件,交換緩衝 (預設操作) glfwSwapBuffers(window); // 交換顏色緩衝(它是一個儲存著GLFW視窗每一個畫素顏色值的大緩衝),它在這一迭代中被用來繪製,並且將會作為輸出顯示在螢幕上。 glfwPollEvents(); // 有沒有觸發什麼事件(比如鍵盤輸入、滑鼠移動等)、更新視窗狀態 } // 解綁 VAO VBO 著色器程式物件 glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteProgram(shaderProgram); // 當渲染迴圈結束後我們需要正確釋放/刪除之前的分配的所有資源 glfwTerminate(); return 0; }