OpenGL創建一個三角形,並且顏色漸變(綠—>黑—>綠)


學習自:

https://learnopengl-cn.github.io/01%20Getting%20started/05%20Shaders/#_4

  1 #include <glad/glad.h>
  2 #include <GLFW/glfw3.h>
  3 
  4 #include <iostream>
  5 #include <cmath>
  6 
  7 void framebuffer_size_callback(GLFWwindow* window, int width, int height);
  8 void processInput(GLFWwindow *window);
  9 
 10 // 設置窗體的寬度和高度
 11 const unsigned int SCR_WIDTH = 800;
 12 const unsigned int SCR_HEIGHT = 600;
 13 
 14 const char *vertexShaderSource = "#version 330 core\n"
 15 "layout (location = 0) in vec3 aPos;\n"
 16 "void main()\n"
 17 "{\n"
 18 "   gl_Position = vec4(aPos, 1.0);\n"
 19 "}\0";
 20 
 21 const char *fragmentShaderSource = "#version 330 core\n"
 22 "out vec4 FragColor;\n"
 23 "uniform vec4 ourColor;\n"
 24 "void main()\n"
 25 "{\n"
 26 "   FragColor = ourColor;\n"
 27 "}\n\0";
 28 
 29 int main()
 30 {
 31     // 初始化glfw
 32     glfwInit();
 33     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
 34     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
 35     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 36 
 37     // 條件編譯語句,如果是蘋果系統?
 38 #ifdef __APPLE__
 39     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
 40 #endif
 41 
 42     // 創建glfw窗體
 43     GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
 44     if (window == NULL)
 45     {
 46         std::cout << "Failed to create GLFW window" << std::endl;
 47         glfwTerminate();
 48         return -1;
 49     }
 50     glfwMakeContextCurrent(window);
 51     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
 52 
 53     // glad: load all OpenGL function pointers
 54     // ---------------------------------------
 55     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
 56     {
 57         std::cout << "Failed to initialize GLAD" << std::endl;
 58         return -1;
 59     }
 60 
 61     // 創建並編譯着色器
 62     // vertex shader
 63     int vertexShader = glCreateShader(GL_VERTEX_SHADER);
 64     //glShaderSource函數把要編譯的着色器對象作為第一個參數。
 65     //第二參數指定了傳遞的源碼字符串數量,這里只有一個。
 66     //第三個參數是頂點着色器真正的源碼。
 67     //第四個參數我們先設置為NULL。
 68     glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
 69     glCompileShader(vertexShader);
 70     // 錯誤檢測
 71     int success;//表示是否編譯成功
 72     char infoLog[512];//存儲錯誤信息
 73     glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
 74     if (!success)
 75     {
 76         glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
 77         std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
 78     }
 79     // 片段着色器
 80     int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
 81     glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
 82     glCompileShader(fragmentShader);
 83     // 錯誤檢測
 84     glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
 85     if (!success)
 86     {
 87         glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
 88         std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
 89     }
 90     // 將着色器鏈接為一個着色器對象
 91     int shaderProgram = glCreateProgram();
 92     glAttachShader(shaderProgram, vertexShader);
 93     glAttachShader(shaderProgram, fragmentShader);
 94     glLinkProgram(shaderProgram);
 95     // 錯誤檢測
 96     glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
 97     if (!success) {
 98         glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
 99         std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
100     }
101     //在把着色器對象鏈接到程序對象以后,記得刪除着色器對象,我們不再需要它們了:
102     glDeleteShader(vertexShader);
103     glDeleteShader(fragmentShader);
104 
105     // 設置頂點
106     float vertices[] = {
107          0.5f, -0.5f, 0.0f,  // bottom right
108         -0.5f, -0.5f, 0.0f,  // bottom left
109          0.0f,  0.5f, 0.0f   // top 
110     };
111     //創建一個VAO——頂點數組對象(Vertex Array Object, VAO)
112     //        VAO可以像頂點緩沖對象那樣被綁定,任何隨后的頂點屬性調用都會儲存在這個VAO中。
113     //創建VBO——頂點緩沖對象:Vertex Buffer Object,VBO
114     //        它會在GPU內存(通常被稱為顯存)中儲存大量頂點。
115     //        使用這些緩沖對象的好處是我們可以一次性的發送一大批數據到顯卡上,而不是每個頂點發送一次。
116     unsigned int VBO, VAO;
117     glGenVertexArrays(1, &VAO);
118     glGenBuffers(1, &VBO);
119     // 1.綁定VOA
120     glBindVertexArray(VAO);
121     // 2.把頂點數組復制到緩沖中供OpenGL使用
122     glBindBuffer(GL_ARRAY_BUFFER, VBO);
123     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
124 
125     /*
126     GL_STATIC_DRAW :數據不會或幾乎不會改變。
127     GL_DYNAMIC_DRAW:數據會被改變很多。
128     GL_STREAM_DRAW :數據每次繪制時都會改變。
129     */
130 
131     // 3.設置頂點屬性指針
132     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
133     glEnableVertexAttribArray(0);
134 
135     glBindVertexArray(VAO);
136 
137 
138     // 循環渲染
139     // -----------
140     while (!glfwWindowShouldClose(window))
141     {
142         // 輸入
143         processInput(window);
144 
145         // 渲染
146         // 清楚顏色緩沖
147         glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
148         glClear(GL_COLOR_BUFFER_BIT);
149 
150         // 記得激活着色器
151         glUseProgram(shaderProgram);
152 
153         // 更新uniform,然后每個渲染迭代都更新這個uniform:
154         /*
155         首先我們通過glfwGetTime()獲取運行的秒數。
156         然后我們使用sin函數讓顏色在0.0到1.0之間改變,
157         最后將結果儲存到greenValue里。
158         */
159         float timeValue = glfwGetTime();
160         float greenValue = sin(timeValue) / 2.0f + 0.5f;
161         /*
162         用glGetUniformLocation查詢uniform ourColor的位置值。
163         如果glGetUniformLocation返回-1就代表沒有找到這個位置值。
164 
165         注意,查詢uniform地址不要求你之前使用過着色器程序,
166         但是更新一個uniform之前你必須先使用程序(調用glUseProgram),
167         因為它是在當前激活的着色器程序中設置uniform的。
168         */
169         int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
170         //最后,我們可以通過glUniform4f函數設置uniform值。
171         glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);
172 
173         // 繪制三角形
174         glDrawArrays(GL_TRIANGLES, 0, 3);
175 
176         // 交換緩沖並查詢IO事件
177         glfwSwapBuffers(window);
178         glfwPollEvents();
179     }
180 
181     // 取消分配的空間
182     glDeleteVertexArrays(1, &VAO);
183     glDeleteBuffers(1, &VBO);
184 
185     // 終止,清除所有先前分配的GLFW資源。
186     glfwTerminate();
187     return 0;
188 }
189 
190 // glfw:點擊esc退出,可是刪掉這一塊前面的東西還會報錯,還是留着吧
191 void processInput(GLFWwindow *window)
192 {
193     if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
194         glfwSetWindowShouldClose(window, true);
195 }
196 
197 // 每當窗口大小發生變化(通過OS或用戶調整大小)時,都會執行此回調函數
198 void framebuffer_size_callback(GLFWwindow* window, int width, int height)
199 {
200     //確保視口與新窗口尺寸匹配; 請注意寬度和
201     //高度將遠遠大於視網膜顯示器上指定的高度。
202     glViewport(0, 0, width, height);
203 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM