學習自:
https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/#3d
0,首先添加glm庫文件
相關方法可以參照我指定的那篇隨便
1,頂點着色器shader.vs
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; out vec2 TexCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0f); TexCoord = vec2(aTexCoord.x, aTexCoord.y); }
2,片段着色器shader.fs
#version 330 core out vec4 FragColor; in vec2 TexCoord; // texture samplers uniform sampler2D texture1; uniform sampler2D texture2; void main() { // linearly interpolate between both textures (80% container, 20% awesomeface) FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2); }
3,主程序

1 #include <glad/glad.h> 2 #include <GLFW/glfw3.h> 3 4 #include <glm/glm.hpp> 5 #include <glm/gtc/matrix_transform.hpp> 6 #include <glm/gtc/type_ptr.hpp> 7 8 #include "stb_image.h" 9 #include "shader_s.h" 10 #include <iostream> 11 12 void framebuffer_size_callback(GLFWwindow* window, int width, int height); 13 void processInput(GLFWwindow *window); 14 15 // settings 16 const unsigned int SCR_WIDTH = 800; 17 const unsigned int SCR_HEIGHT = 600; 18 19 int main() 20 { 21 // glfw: initialize and configure 22 // ------------------------------ 23 glfwInit(); 24 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 25 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 26 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 27 28 #ifdef __APPLE__ 29 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X 30 #endif 31 32 // glfw window creation 33 // -------------------- 34 GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); 35 if (window == NULL) 36 { 37 std::cout << "Failed to create GLFW window" << std::endl; 38 glfwTerminate(); 39 return -1; 40 } 41 glfwMakeContextCurrent(window); 42 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); 43 44 // glad: load all OpenGL function pointers 45 // --------------------------------------- 46 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) 47 { 48 std::cout << "Failed to initialize GLAD" << std::endl; 49 return -1; 50 } 51 52 // configure global opengl state 53 // ----------------------------- 54 glEnable(GL_DEPTH_TEST); 55 56 // build and compile our shader zprogram 57 // ------------------------------------ 58 Shader ourShader("../res/textures/texture.vs", "../res/textures/texture.fs"); 59 60 // set up vertex data (and buffer(s)) and configure vertex attributes 61 // ------------------------------------------------------------------ 62 /* 63 float vertices[] = { 64 // 位置信息 // 顏色信息 // 紋理 coords 65 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上 66 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下 67 -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下 68 -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上 69 }; 70 unsigned int indices[] = { 71 0, 1, 3, // 第一個三角形 72 1, 2, 3 // 第二個三角形 73 }; 74 */ 75 float vertices[] = { 76 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 77 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 78 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 79 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 80 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 81 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 82 83 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 84 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 85 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 86 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 87 -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 88 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 89 90 -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 91 -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 92 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 93 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 94 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 95 -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 96 97 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 98 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 99 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 100 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 101 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 102 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 103 104 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 105 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 106 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 107 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 108 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 109 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 110 111 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 112 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 113 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 114 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 115 -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 116 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f 117 }; 118 119 unsigned int VBO, VAO; 120 glGenVertexArrays(1, &VAO); 121 glGenBuffers(1, &VBO); 122 123 glBindVertexArray(VAO); 124 125 glBindBuffer(GL_ARRAY_BUFFER, VBO); 126 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 127 128 // position attribute 129 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); 130 glEnableVertexAttribArray(0); 131 // texture coord attribute 132 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); 133 glEnableVertexAttribArray(1); 134 135 // 加載並創建紋理 136 // ------------------------- 137 unsigned int texture1, texture2; 138 // 第一張紋理 139 140 glGenTextures(1, &texture1); 141 glBindTexture(GL_TEXTURE_2D, texture1); 142 // 為當前綁定的紋理對象設置環繞、過濾方式 143 // 將紋理包裝設置為GL_REPEAT(默認包裝方法) 144 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 145 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 146 // 設置紋理過濾參數 147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 149 // 加載並生成紋理 150 int width, height, nrChannels; 151 stbi_set_flip_vertically_on_load(true); //告訴stb_image.h在y軸上翻轉加載的紋理。 152 153 unsigned char *data = stbi_load("../res/textures/container.jpg", &width, &height, &nrChannels, 0); 154 if (data) 155 { 156 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); 157 glGenerateMipmap(GL_TEXTURE_2D); 158 } 159 else 160 { 161 std::cout << "Failed to load texture" << std::endl; 162 } 163 stbi_image_free(data); 164 165 166 // texture 2 167 glGenTextures(1, &texture2); 168 glBindTexture(GL_TEXTURE_2D, texture2); 169 // set the texture wrapping parameters 170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) 171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 172 // set texture filtering parameters 173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 175 // load image, create texture and generate mipmaps 176 data = stbi_load("../res/textures/awesomeface.png", &width, &height, &nrChannels, 0); 177 if (data) 178 { 179 //請注意,awesomeface.png具有透明度,因此具有alpha通道, 180 //因此請務必告訴OpenGL數據類型為GL_RGBA 181 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 182 glGenerateMipmap(GL_TEXTURE_2D); 183 } 184 else 185 { 186 std::cout << "Failed to load texture" << std::endl; 187 } 188 stbi_image_free(data); 189 190 //告訴每個采樣器的opengl它屬於哪個紋理單元(只需要做一次) 191 ourShader.use(); //激活着色器 192 // either set it manually like so: 193 glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0); 194 // or set it via the texture class 195 ourShader.setInt("texture2", 1); 196 197 198 199 // render loop 200 // ----------- 201 while (!glfwWindowShouldClose(window)) 202 { 203 // input 204 // ----- 205 processInput(window); 206 207 // render 208 // ------ 209 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 210 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // also clear the depth buffer now! 211 212 // bind textures on corresponding texture units 213 glActiveTexture(GL_TEXTURE0); 214 glBindTexture(GL_TEXTURE_2D, texture1); 215 glActiveTexture(GL_TEXTURE1); 216 glBindTexture(GL_TEXTURE_2D, texture2); 217 218 // activate shader 219 ourShader.use(); 220 221 // create transformations 222 glm::mat4 model = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first 223 glm::mat4 view = glm::mat4(1.0f); 224 glm::mat4 projection = glm::mat4(1.0f); 225 model = glm::rotate(model, (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f)); 226 view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f)); 227 projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); 228 // retrieve the matrix uniform locations 229 unsigned int modelLoc = glGetUniformLocation(ourShader.ID, "model"); 230 unsigned int viewLoc = glGetUniformLocation(ourShader.ID, "view"); 231 // pass them to the shaders (3 different ways) 232 glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); 233 glUniformMatrix4fv(viewLoc, 1, GL_FALSE, &view[0][0]); 234 // note: currently we set the projection matrix each frame, but since the projection matrix rarely changes it's often best practice to set it outside the main loop only once. 235 ourShader.setMat4("projection", projection); 236 237 // render box 238 glBindVertexArray(VAO); 239 glDrawArrays(GL_TRIANGLES, 0, 36); 240 241 242 // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) 243 // ------------------------------------------------------------------------------- 244 glfwSwapBuffers(window); 245 glfwPollEvents(); 246 } 247 248 // optional: de-allocate all resources once they've outlived their purpose: 249 // ------------------------------------------------------------------------ 250 glDeleteVertexArrays(1, &VAO); 251 glDeleteBuffers(1, &VBO); 252 //glDeleteBuffers(1, &EBO); 253 254 // glfw: terminate, clearing all previously allocated GLFW resources. 255 // ------------------------------------------------------------------ 256 glfwTerminate(); 257 return 0; 258 } 259 260 // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly 261 // --------------------------------------------------------------------------------------------------------- 262 void processInput(GLFWwindow *window) 263 { 264 if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) 265 glfwSetWindowShouldClose(window, true); 266 } 267 268 // glfw: whenever the window size changed (by OS or user resize) this callback function executes 269 // --------------------------------------------------------------------------------------------- 270 void framebuffer_size_callback(GLFWwindow* window, int width, int height) 271 { 272 // make sure the viewport matches the new window dimensions; note that width and 273 // height will be significantly larger than specified on retina displays. 274 glViewport(0, 0, width, height); 275 }
注意一點的是,我們的着色器類,在這里要添加幾個方法,我去百度了一下,找到了常用的一些方法,把各個類型的的set函數都加進來了。

1 #include "shader_s.h" 2 3 Shader::Shader(const GLchar * vertexPath, const GLchar * fragmentPath) 4 { 5 // 1. 從文件路徑中獲取頂點/片段着色器 6 std::string vertexCode; 7 std::string fragmentCode; 8 std::ifstream vShaderFile; 9 std::ifstream fShaderFile; 10 // 保證ifstream對象可以拋出異常: 11 vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); 12 fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); 13 try 14 { 15 // 打開文件 16 vShaderFile.open(vertexPath); 17 fShaderFile.open(fragmentPath); 18 std::stringstream vShaderStream, fShaderStream; 19 // 讀取文件的緩沖內容到數據流中 20 vShaderStream << vShaderFile.rdbuf(); 21 fShaderStream << fShaderFile.rdbuf(); 22 // 關閉文件處理器 23 vShaderFile.close(); 24 fShaderFile.close(); 25 // 轉換數據流到string 26 vertexCode = vShaderStream.str(); 27 fragmentCode = fShaderStream.str(); 28 } 29 catch (std::ifstream::failure e) 30 { 31 std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; 32 } 33 const char* vShaderCode = vertexCode.c_str(); 34 const char * fShaderCode = fragmentCode.c_str(); 35 // 2. 編譯着色器 36 unsigned int vertex, fragment; 37 // 頂點着色器 vs 38 vertex = glCreateShader(GL_VERTEX_SHADER); 39 glShaderSource(vertex, 1, &vShaderCode, NULL); 40 glCompileShader(vertex); 41 checkCompileErrors(vertex, "VERTEX"); 42 // 片段着色器 fs 43 fragment = glCreateShader(GL_FRAGMENT_SHADER); 44 glShaderSource(fragment, 1, &fShaderCode, NULL); 45 glCompileShader(fragment); 46 checkCompileErrors(fragment, "FRAGMENT"); 47 // 着色器程序 48 ID = glCreateProgram(); 49 glAttachShader(ID, vertex); 50 glAttachShader(ID, fragment); 51 glLinkProgram(ID); 52 checkCompileErrors(ID, "PROGRAM"); 53 // 刪除着色器,它們已經鏈接到我們的程序中了,已經不再需要了 glDeleteShader(vertex); 54 glDeleteShader(fragment); 55 } 56 57 void Shader::use() 58 { 59 glUseProgram(ID); 60 } 61 62 void Shader::setBool(const std::string & name, bool value) const 63 { 64 glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); 65 } 66 67 void Shader::setInt(const std::string & name, int value) const 68 { 69 glUniform1i(glGetUniformLocation(ID, name.c_str()), value); 70 } 71 72 void Shader::setFloat(const std::string & name, float value) const 73 { 74 glUniform1f(glGetUniformLocation(ID, name.c_str()), value); 75 } 76 77 void Shader::setVec2(const std::string & name, const glm::vec2 & value) const 78 { 79 glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); 80 } 81 82 void Shader::setVec2(const std::string & name, float x, float y) const 83 { 84 glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y); 85 } 86 87 void Shader::setVec3(const std::string & name, const glm::vec3 & value) const 88 { 89 glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); 90 } 91 92 void Shader::setVec3(const std::string & name, float x, float y, float z) const 93 { 94 glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); 95 } 96 97 void Shader::setVec4(const std::string & name, const glm::vec4 & value) const 98 { 99 glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); 100 } 101 102 void Shader::setVec4(const std::string & name, float x, float y, float z, float w) 103 { 104 glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w); 105 } 106 107 void Shader::setMat2(const std::string & name, const glm::mat2 & mat) const 108 { 109 glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); 110 } 111 112 void Shader::setMat3(const std::string & name, const glm::mat3 & mat) const 113 { 114 glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); 115 } 116 117 void Shader::setMat4(const std::string & name, const glm::mat4 & mat) const 118 { 119 glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]); 120 } 121 122 void Shader::checkCompileErrors(unsigned int shader, std::string type) 123 { 124 int success; 125 char infoLog[1024]; 126 if (type != "PROGRAM") 127 { 128 glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 129 if (!success) 130 { 131 glGetShaderInfoLog(shader, 1024, NULL, infoLog); 132 std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; 133 } 134 } 135 else 136 { 137 glGetProgramiv(shader, GL_LINK_STATUS, &success); 138 if (!success) 139 { 140 glGetProgramInfoLog(shader, 1024, NULL, infoLog); 141 std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl; 142 } 143 } 144 }
自己把相關的類定義寫道頭文件中就可以了。
4,運行結果