1.当片段着色器处理完一个片段之后,模板测试(stencil test)会开始执行,和深度测试一样,它也可能会丢弃片段,接下来,被保留的片段会进入深度测试
2.每个窗口库都需要为你配置一个模板缓冲,但是GLFW这个窗口库会自动做这件事,所以不用告诉GLFW来创建一个模板缓冲
3.场景中的片段将只会在片段的模板值为1的时候被渲染,其他的都被丢弃了
启用模板缓冲的写入
渲染物体,更新模板缓冲的内容
禁用模板缓冲的写入
渲染其他物体,这次根据模板缓冲的内容丢弃特定的片段
用来配置模板缓冲的两个函数,glStencilFunc和glStencilOp
glStencilFunc(GLenum func, GLint ref, GLuint mash)一共包含三个参数:
func:设置模板测试函数(Stencil Test Function),这个测试函数将会应用到已存储的的模板值上和GLstenciFunc函数的ref值上,
可用的选项有:GL_NEVER/ GL_LESS/ GL_LEQUAL / GL_GREATER / GL_AEAUAL / GL_EQUAL / GL_NOTEQUAL和 GL_ALWAYS
ref:设置了模板测试的参考值(Reference Value), 模板缓冲的内容将会与这个值进行比较
mask:设置一个掩码,它将会与参考值和村初值在测试比较他们之前进行与(and)运算,初识情况下所有为都为1
但是glStencilFunc只描述了OpenGL应该对模板缓冲内容做什么,而不是我们应该如何更新缓冲,所以就需要glStencilOp这个函数了
glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass)一共包含三个选项,我们能够设置每个选项应该采取的行为
sfail:模板测试失败是采取的行为
dpfail:模板测试通过,但深度测试失败采取的行为
dppass:模板测试和深度测试都通过时采取的行为
1 /** 2 * glBlendFunc混合两种颜色的函数 3 *glBlendFunc(GLenum sfactor, GLenum dfactor)函数接受两个参数,来设置源和目标因子 4 *常数颜色向量Cconstan可以通过glBlendColor函数来另外设置* 5 *glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 6 *也可以使用glBlendFuncSeparate为RGB和alpha通道分别设置不同的选项 7 * glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_GL_ZERO); 8 *glBlendEquation(GLenum mode)允许我们设置运算符 9 *GL_FUNC_ADD:默认选项,将两个分量相加,Cr = S + D 10 *GL_FUNC_SUBTRACT = S - D 11 *GL_FUNC_REVERSE_SUBTRACT,将两个分量向减,但顺序相反*/ 12 13 /** 14 *当绘制一个有不透明和透明物体的场景的时候,大体的原则如下: 15 *1.先绘制所有不透明的物体。 16 *2.对所有透明的物体排序。 17 *3.按顺序绘制所有透明的物体。**/ 18 19 20 21 #include <iostream> 22 #include <vector> 23 #include <map> 24 25 using namespace std; 26 #define GLEW_STATIC 27 28 #include <GL/glew.h> 29 #include <GLFW/glfw3.h> 30 31 #include "stb_image.h" 32 33 #include <glm/glm.hpp> 34 #include <glm/gtc/matrix_transform.hpp> 35 #include <glm/gtc/type_ptr.hpp> 36 37 #include "Shader.h" 38 #include "camera.h" 39 //#include "Model.h" 40 41 void framebuffer_size_callback(GLFWwindow* window, int width, int height); 42 void mouse_callback(GLFWwindow* window, double xpos, double ypos); 43 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); 44 void processInput(GLFWwindow* window); 45 unsigned int loadTexture(const char *path); 46 47 //setting 48 const unsigned int SCR_WIDTH = 800; 49 const unsigned int SCR_HEIGHT = 600; 50 51 //camera 52 Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); 53 float lastX = (float)SCR_WIDTH / 2; 54 float lastY = (float)SCR_HEIGHT / 2; 55 bool firstMouse = true; 56 57 //timing 58 float deltaTime = 0.0f; 59 float lastFrame = 0.0f; 60 61 int main() 62 { 63 glfwInit(); 64 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 65 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 66 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 67 68 GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LEARNOPENGL", NULL, NULL); 69 if (window == NULL) 70 { 71 std::cout << "Failed to create window!" << std::endl; 72 glfwTerminate(); 73 return -1; 74 } 75 glfwMakeContextCurrent(window); 76 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); 77 glfwSetCursorPosCallback(window, mouse_callback); 78 glfwSetScrollCallback(window, scroll_callback); 79 80 //tell GLFW to capture our mouse 81 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); 82 83 glewExperimental = GL_TRUE; 84 if (glewInit() != GLEW_OK) 85 { 86 std::cout << "Failed to initialize GLEW!" << std::endl; 87 return -1; 88 } 89 90 ////configure global opengl state 91 //glEnable(GL_DEPTH_TEST); //启用深度测试,默认情况下是禁用的 92 //glDepthFunc(GL_LESS); //always pass the depth test(same effect as glDisable(GL_DEPTH_TEST)//禁用深度测试,永远都通过深度测试 93 ////glDepthMask(GL_FALSE); //深度掩码,可以禁用深度缓冲的写入 94 95 //glEnable(GL_STENCIL_TEST); 96 ////glStencilMask(0x00); //位掩码, 每个模板值都为0, 每一位在写入模板缓冲时都会变成0(禁用写入) 97 //glStencilMask(0xff); //每个模板值都为1,每一位写入模板缓冲时都保持原样 98 99 //glStencilFunc(GL_EQUAL, 1, 0xFF); //只要一个片段的模板值等于参考值1,片段将会通过测试并被绘制,否则会被被丢弃 100 //glStencilOp(GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP);//默认情况下,glStencilOp是设置为这样的,所以不论任何测试的结果是如何,模板缓冲都会保留它的值 101 ////默认的行为不会更新模板缓冲,所以如果你想写入模板缓冲的话,至少对其中一个选项设置不同的值 102 glEnable(GL_DEPTH_TEST); 103 glDepthFunc(GL_LESS); 104 glEnable(GL_BLEND); //启用混合 105 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 106 107 //build and compile shaders 108 Shader shader("E:\C++\HigherOpenGL\1.2.1ver1.txt", "E:\C++\HigherOpenGL\1.3.2Frag1.txt"); 109 110 float cubeVertices[] = { 111 //position //texture Coords 112 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 113 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 114 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 115 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 116 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 117 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 118 119 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 120 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 121 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 122 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 123 -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 124 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 125 126 -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 127 -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 128 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 129 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 130 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 131 -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 132 133 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 134 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 135 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 136 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 137 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 138 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 139 140 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 141 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 142 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 143 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 144 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 145 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 146 147 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 148 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 149 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 150 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 151 -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 152 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f 153 }; 154 155 float floorVertices[] = { 156 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, 157 -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, 158 -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 159 160 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, 161 -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 162 5.0f, -0.5f, -5.0f, 2.0f, 2.0f 163 }; 164 165 float grassVertices[] = { 166 1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 167 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 168 0.0f, 0.5f, 0.0f, 0.0f, 1.0f, 169 1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 170 0.0f, 0.5f, 0.0f, 0.0f, 1.0f, 171 1.0f, 0.5f, 0.0f, 1.0f, 1.0f 172 }; 173 174 vector<glm::vec3> vegetation; 175 vegetation.push_back(glm::vec3(-1.5f, 0.0f, -0.48f)); 176 vegetation.push_back(glm::vec3(1.5f, 0.0f, 0.51f)); 177 vegetation.push_back(glm::vec3(0.0f, 0.0f, 0.7f)); 178 vegetation.push_back(glm::vec3(-0.3f, 0.0f, -2.3f)); 179 vegetation.push_back(glm::vec3(0.5f, 0.0f, -0.6f)); 180 181 //cube VAO 182 unsigned int cubeVAO, cubeVBO; 183 glGenVertexArrays(1, &cubeVAO); 184 glGenBuffers(1, &cubeVBO); 185 glBindVertexArray(cubeVAO); 186 glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); 187 glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW); 188 glEnableVertexAttribArray(0); 189 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); 190 glEnableVertexAttribArray(1); 191 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); 192 glBindVertexArray(0); 193 194 //floor VAO 195 unsigned int floorVAO, floorVBO; 196 glGenVertexArrays(1, &floorVAO); 197 glGenBuffers(1, &floorVBO); 198 glBindVertexArray(floorVAO); 199 glBindBuffer(GL_ARRAY_BUFFER, floorVBO); 200 glBufferData(GL_ARRAY_BUFFER, sizeof(floorVertices), floorVertices, GL_STATIC_DRAW); 201 glEnableVertexAttribArray(0); 202 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); 203 glEnableVertexAttribArray(1); 204 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); 205 glBindVertexArray(0); 206 207 unsigned grassVAO, grassVBO; 208 glGenVertexArrays(1, &grassVAO); 209 glGenBuffers(1, &grassVBO); 210 glBindVertexArray(grassVAO); 211 glBindBuffer(GL_ARRAY_BUFFER, grassVBO); 212 glBufferData(GL_ARRAY_BUFFER, sizeof(grassVertices), grassVertices, GL_STATIC_DRAW); 213 glEnableVertexAttribArray(0); 214 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); 215 glEnableVertexAttribArray(1); 216 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); 217 218 219 //load textures 220 stbi_set_flip_vertically_on_load(true); 221 unsigned int cubeTexture = loadTexture("greenWall.jpg"); 222 unsigned int floorTexture = loadTexture("floor.jpg"); 223 unsigned int grassTexture = loadTexture("glass.png"); 224 225 shader.use(); 226 glUniform1i(glGetUniformLocation(shader.ID, "texture1"), 0); 227 228 229 230 //render loop 231 while (!glfwWindowShouldClose(window)) 232 { 233 //per-frame time logic 234 float currentFrame = glfwGetTime(); 235 deltaTime = currentFrame - lastFrame; 236 lastFrame = currentFrame; 237 238 //input 239 processInput(window); 240 241 //render 242 glClearColor(0.1f, 0.1f, 0.1f, 1.0f); 243 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 244 245 shader.use(); 246 glm::mat4 model; 247 glm::mat4 view = camera.GetViewMatrix(); 248 glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); 249 shader.setMat4("view", view); 250 glUniformMatrix4fv(glGetUniformLocation(shader.ID, "projection"), 1, GL_FALSE, glm::value_ptr(projection)); 251 252 253 254 //floor 255 glBindVertexArray(floorVAO); 256 glActiveTexture(GL_TEXTURE0); 257 glBindTexture(GL_TEXTURE_2D, floorTexture); 258 shader.setMat4("model", glm::mat4()); 259 glDrawArrays(GL_TRIANGLES, 0, 6); 260 //glBindVertexArray(0); 261 262 //cube 263 glBindVertexArray(cubeVAO); 264 glActiveTexture(GL_TEXTURE0); 265 glBindTexture(GL_TEXTURE_2D, cubeTexture); 266 model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f)); 267 glUniformMatrix4fv(glGetUniformLocation(shader.ID, "model"), 1, GL_FALSE, glm::value_ptr(model)); 268 glDrawArrays(GL_TRIANGLES, 0, 36); 269 model = glm::mat4(); 270 model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f)); //the second cube 271 shader.setMat4("model", model); 272 glDrawArrays(GL_TRIANGLES, 0, 36); 273 274 //我们把距离和它对应的位置向量存储到一个STL库的map数据结构中,map会自动根据健值(key)对它的值进行排序, 275 //所以只要我们添加了所有的位置,并以他的距离作为键,它们就会自动根据距离值排序了 276 std::map<float, glm::vec3> sorted; 277 for (unsigned int i = 0; i < vegetation.size(); i++) 278 { 279 float distance = glm::length(camera.Position - vegetation[i]); 280 sorted[distance] = vegetation[i]; //一个距离对应一个位置 281 } 282 //结果就是一个排序后的容器对象,它根据distance健值从低到高存储了每个窗户的位置 283 284 //之后,这次在渲染的时候,我们将以逆序(从远到近)从map中获取值,之后以正确的顺序绘制对应的窗户 285 /*glBindVertexArray(grassVAO); 286 glBindTexture(GL_TEXTURE_2D, grassTexture); 287 for (std::map<float, glm::vec3>::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); it++) 288 { 289 model = glm::mat4(); 290 model = glm::translate(model, it->second); 291 shader.setMat4("model", model); 292 glDrawArrays(GL_TRIANGLES, 0, 6); 293 }*/ 294 295 296 297 298 glBindVertexArray(grassVAO); 299 glBindTexture(GL_TEXTURE_2D, grassTexture); 300 for (unsigned int i = 0; i < vegetation.size(); i++) 301 { 302 model = glm::mat4(); 303 model = glm::translate(model, vegetation[i]); 304 shader.setMat4("model", model); 305 glDrawArrays(GL_TRIANGLES, 0, 6); 306 } 307 308 //glfw: swap buffers and poll IO events (keys pressed / released, mouse moved etc.) 309 glfwSwapBuffers(window); 310 glfwPollEvents(); 311 } 312 313 //optional: de - allocate all resources once they've outlived their purpose; 314 glDeleteVertexArrays(1, &cubeVAO); 315 glDeleteVertexArrays(1, &floorVAO); 316 glDeleteBuffers(1, &cubeVBO); 317 glDeleteBuffers(1, &floorVBO); 318 319 glfwTerminate(); 320 return 0; 321 } 322 323 void processInput(GLFWwindow *window) 324 { 325 if (glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_PRESS) 326 glfwSetWindowShouldClose(window, true); 327 if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) 328 camera.ProcessKeyboard(FORWARD, deltaTime); 329 if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) 330 camera.ProcessKeyboard(BACKWARD, deltaTime); 331 if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) 332 camera.ProcessKeyboard(LEFT, deltaTime); 333 if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) 334 camera.ProcessKeyboard(RIGHT, deltaTime); 335 } 336 337 void framebuffer_size_callback(GLFWwindow* window, int width, int height) 338 { 339 glViewport(0, 0, width, height); 340 } 341 342 void mouse_callback(GLFWwindow *window, double xpos, double ypos) 343 { 344 if (firstMouse) 345 { 346 lastX = xpos; 347 lastY = ypos; 348 firstMouse = false; 349 } 350 351 float xoffset = xpos - lastX; 352 float yoffset = lastY - ypos; 353 354 lastX = xpos; 355 lastY = ypos; 356 357 camera.ProcessMouseMovement(xoffset, yoffset); 358 } 359 360 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) 361 { 362 camera.ProcessMouseScroll(yoffset); 363 } 364 365 unsigned int loadTexture(char const *path) 366 { 367 unsigned int textureID; 368 glGenTextures(1, &textureID); 369 370 int width, height, nrChannels; 371 unsigned char *data = stbi_load(path, &width, &height, &nrChannels, 0); 372 if (data) 373 { 374 GLenum format; 375 if (nrChannels == 1) 376 format = GL_RED; 377 else if (nrChannels == 3) 378 format = GL_RGB; 379 else if (nrChannels == 4) 380 format = GL_RGBA; 381 382 glBindTexture(GL_TEXTURE_2D, textureID); 383 //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 384 glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); //create a texture 385 glGenerateMipmap(GL_TEXTURE_2D); 386 387 /*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 388 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);*/ 389 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 390 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 391 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 392 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 393 394 stbi_image_free(data); 395 } 396 else 397 { 398 std::cout << "Texture failed to load at path: " << path << std::endl; 399 stbi_image_free(data); 400 } 401 return textureID; 402 403 }
Shader.h
1 #ifndef SHADER_H_INCLUDE 2 #define SHADER_H_INCLUDE 3 4 #include <iostream> 5 #include <string> 6 #include <sstream> 7 #include <fstream> 8 9 #include <GL/glew.h> 10 #include <GLFW/glfw3.h> 11 #include <glm/glm.hpp> 12 #include <glm/gtc/matrix_transform.hpp> 13 #include <glm/gtc/type_ptr.hpp> 14 15 class Shader { 16 public: 17 unsigned int ID; 18 19 Shader(const GLchar* vertexPath, const GLchar* fragmentPath) 20 { 21 std::string vertexCode; 22 std::string fragmentCode; 23 std::ifstream vShaderFile; 24 std::ifstream fShaderFile; 25 26 vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); 27 fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); 28 29 try { 30 //open files 31 vShaderFile.open(vertexPath); 32 fShaderFile.open(fragmentPath); 33 34 std::stringstream vShaderStream, fShaderStream; 35 36 //read file's buffer contents into streams 37 vShaderStream << vShaderFile.rdbuf(); 38 fShaderStream << fShaderFile.rdbuf(); 39 40 //close file handlers 41 vShaderFile.close(); 42 fShaderFile.close(); 43 44 //convert stream into string 45 vertexCode = vShaderStream.str(); 46 fragmentCode = fShaderStream.str(); 47 } 48 catch (std::ifstream::failure e) 49 { 50 std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl; 51 } 52 const char* vShaderCode = vertexCode.c_str(); 53 const char* fShaderCode = fragmentCode.c_str(); 54 55 //2.compile shaders 56 unsigned int vertex, fragment; 57 int success; 58 char infoLog[512]; 59 60 //vertex shader 61 vertex = glCreateShader(GL_VERTEX_SHADER); 62 glShaderSource(vertex, 1, &vShaderCode, NULL); 63 glCompileShader(vertex); 64 glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); 65 if (!success) 66 { 67 glGetShaderInfoLog(vertex, 512, NULL, infoLog); 68 std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED!" << std::endl; 69 } 70 71 fragment = glCreateShader(GL_FRAGMENT_SHADER); 72 glShaderSource(fragment, 1, &fShaderCode, NULL); 73 glCompileShader(fragment); 74 glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); 75 if (!success) 76 { 77 glGetShaderInfoLog(fragment, 512, NULL, infoLog); 78 std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED!" << std::endl; 79 } 80 81 ID = glCreateProgram(); 82 glAttachShader(ID, vertex); 83 glAttachShader(ID, fragment); 84 glLinkProgram(ID); 85 glGetProgramiv(ID, GL_LINK_STATUS, &success); 86 if (!success) 87 { 88 glGetProgramInfoLog(ID, 512, NULL, infoLog); 89 std::cout << "ERROR::SHADER::PROGRAM::LINKTING_FAILED!" << std::endl; 90 } 91 92 //delete the shaders sa they are linked into our program now and no long necessary 93 glDeleteShader(vertex); 94 glDeleteShader(fragment); 95 } 96 97 //activate the shader 98 void use() 99 { 100 glUseProgram(ID); 101 } 102 103 //utility uniform functions 104 void setBool(const std::string &name, bool value) const 105 { 106 glUniform1i(glGetUniformLocation(ID, name.c_str()), value); 107 } 108 109 void setInt(const std::string &name, int value) const 110 { 111 glUniform1i(glGetUniformLocation(ID, name.c_str()), value); 112 } 113 114 void setFloat(const std::string &name, float value) const 115 { 116 glUniform1f(glGetUniformLocation(ID, name.c_str()), value); 117 } 118 119 void setVec3(const std::string &name, const glm::vec3 &value) const 120 { 121 glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]); 122 } 123 124 void setVec3(const std::string &name, float x, float y, float z) const 125 { 126 glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z); 127 } 128 129 130 void setMat4(const std::string &name, glm::mat4 &trans) const 131 { 132 133 glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &trans[0][0]); 134 } 135 136 137 /*void setMat4(const std::string &name, glm::mat4 trans) const 138 { 139 140 //'trans': formal parameter with requested alignment of 16 won't be aligned,请求对齐的16的形式参数不会对齐 141 glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(trans)); 142 }*/ 143 144 }; 145 146 #endif
camera.h
1 #ifndef CAMERA_H 2 #define CAMERA_H 3 4 #include <GL/glew.h> 5 #include <glm/glm.hpp> 6 #include <glm/gtc/matrix_transform.hpp> 7 8 #include <vector> 9 10 // Defines several possible options for camera movement. Used as abstraction to stay away from window-system specific input methods 11 enum Camera_Movement { 12 FORWARD, 13 BACKWARD, 14 LEFT, 15 RIGHT 16 }; 17 18 // Default camera values 19 const float YAW = -90.0f; 20 const float PITCH = 0.0f; 21 const float SPEED = 2.5f; 22 const float SENSITIVITY = 0.1f; 23 const float ZOOM = 45.0f; 24 25 26 // An abstract camera class that processes input and calculates the corresponding Euler Angles, Vectors and Matrices for use in OpenGL 27 class Camera 28 { 29 public: 30 // Camera Attributes 31 glm::vec3 Position; 32 glm::vec3 Front; 33 glm::vec3 Up; 34 glm::vec3 Right; 35 glm::vec3 WorldUp; 36 // Euler Angles 37 float Yaw; 38 float Pitch; 39 // Camera options 40 float MovementSpeed; 41 float MouseSensitivity; 42 float Zoom; 43 44 // Constructor with vectors 45 Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM) 46 { 47 Position = position; 48 WorldUp = up; 49 Yaw = yaw; 50 Pitch = pitch; 51 updateCameraVectors(); 52 } 53 // Constructor with scalar values 54 Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM) 55 { 56 Position = glm::vec3(posX, posY, posZ); 57 WorldUp = glm::vec3(upX, upY, upZ); 58 Yaw = yaw; 59 Pitch = pitch; 60 updateCameraVectors(); 61 } 62 63 // Returns the view matrix calculated using Euler Angles and the LookAt Matrix 64 glm::mat4 GetViewMatrix() 65 { 66 return glm::lookAt(Position, Position + Front, Up); 67 } 68 69 // Processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems) 70 void ProcessKeyboard(Camera_Movement direction, float deltaTime) 71 { 72 float velocity = MovementSpeed * deltaTime; 73 if (direction == FORWARD) 74 Position += Front * velocity; 75 if (direction == BACKWARD) 76 Position -= Front * velocity; 77 if (direction == LEFT) 78 Position -= Right * velocity; 79 if (direction == RIGHT) 80 Position += Right * velocity; 81 } 82 83 // Processes input received from a mouse input system. Expects the offset value in both the x and y direction. 84 void ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch = true) 85 { 86 xoffset *= MouseSensitivity; 87 yoffset *= MouseSensitivity; 88 89 Yaw += xoffset; 90 Pitch += yoffset; 91 92 // Make sure that when pitch is out of bounds, screen doesn't get flipped 93 if (constrainPitch) 94 { 95 if (Pitch > 89.0f) 96 Pitch = 89.0f; 97 if (Pitch < -89.0f) 98 Pitch = -89.0f; 99 } 100 101 // Update Front, Right and Up Vectors using the updated Euler angles 102 updateCameraVectors(); 103 } 104 105 // Processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis 106 void ProcessMouseScroll(float yoffset) 107 { 108 if (Zoom >= 1.0f && Zoom <= 45.0f) //zoom缩放,就是视野 109 Zoom -= yoffset; 110 if (Zoom <= 1.0f) 111 Zoom = 1.0f; 112 if (Zoom >= 45.0f) 113 Zoom = 45.0f; 114 } 115 116 private: 117 // Calculates the front vector from the Camera's (updated) Euler Angles 118 void updateCameraVectors() 119 { 120 // Calculate the new Front vector 121 glm::vec3 front; 122 front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch)); 123 front.y = sin(glm::radians(Pitch)); 124 front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch)); 125 Front = glm::normalize(front); 126 // Also re-calculate the Right and Up vector 127 Right = glm::normalize(glm::cross(Front, WorldUp)); // Normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement. 128 Up = glm::normalize(glm::cross(Right, Front)); 129 } 130 }; 131 #endif
图片: