Lighting maps_练习二
添加一个叫做放射光贴图(Emission Map)的东西,它是一个储存了每个片段的发光值(Emission Value)的贴图。发光值是一个包含(假设)光源的物体发光(Emit)时可能显现的颜色,这样的话物体就能够忽略光照条件进行发光(Glow)。游戏中某个物体在发光的时候,你通常看到的就是放射光贴图(比如 机器人的眼,或是箱子上的灯带)。将这个纹理(作者为 creativesam)作为放射光贴图添加到箱子上,产生这些字母都在发光的效果
片段着色器代码:
1 #version 330 core 2 struct Material { 3 sampler2D diffuse; 4 sampler2D specular; 5 sampler2D emission; 6 float shininess; 7 }; 8 9 struct Light { 10 vec3 position; 11 12 vec3 ambient; 13 vec3 diffuse; 14 vec3 specular; 15 }; 16 17 in vec2 TexCoords; 18 in vec3 Normal; 19 in vec3 FragPos; 20 out vec4 FragColor; 21 22 uniform Material material; 23 uniform Light light; 24 uniform vec3 viewPos; 25 uniform sampler2D creativesam; 26 27 void main() 28 { 29 // 环境光 30 vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); 31 32 // 漫反射 33 vec3 norm = normalize(Normal); 34 vec3 lightDir = normalize(light.position - FragPos); 35 float diff = max(dot(norm, lightDir), 0.0); 36 vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); 37 38 // 镜面光 39 vec3 viewDir = normalize(viewPos - FragPos); 40 vec3 reflectDir = reflect(-lightDir, norm); 41 float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); 42 vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); 43 44 // emission 45 vec3 emission = vec3(texture(material.emission, TexCoords)); 46 47 vec3 result = ambient + diffuse + specular + emission; 48 FragColor = vec4(result, 1.0); 49 }
完整代码:
1 #include <glad/glad.h> 2 #include <GLFW/glfw3.h> 3 #define STB_IMAGE_IMPLEMENTATION 4 #include <stb/stb_image.h> 5 6 #include <glm/glm.hpp> 7 #include <glm/gtc/matrix_transform.hpp> 8 #include <glm/gtc/type_ptr.hpp> 9 10 #include <Shader/shader.h> 11 #include <Camera/camera.h> 12 13 #include <iostream> 14 15 void framebuffer_size_callback(GLFWwindow* window, int width, int height); 16 void mouse_callback(GLFWwindow* window, double xpos, double ypos); 17 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); 18 void processInput(GLFWwindow *window); 19 unsigned int loadTexture(const char *path); 20 21 // settings 22 const unsigned int SCR_WIDTH = 800; 23 const unsigned int SCR_HEIGHT = 600; 24 25 // camera 26 Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); 27 float lastX = SCR_WIDTH / 2.0f; 28 float lastY = SCR_HEIGHT / 2.0f; 29 bool firstMouse = true; 30 31 //timeing 32 float deltaTime = 0.0f; // 当前帧与上一帧的时间差 33 float lastFrame = 0.0f; // 上一帧的时间 34 35 // lighting 36 glm::vec3 lightPos(1.2f, 1.0f, 2.0f); 37 38 int main() 39 { 40 // glfw: initialize and configure 41 // ------------------------------ 42 glfwInit(); 43 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 44 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 45 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 46 47 #ifdef __APPLE__ 48 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X 49 #endif 50 51 // glfw window creation 52 // -------------------- 53 GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); 54 if (window == NULL) 55 { 56 std::cout << "Failed to create GLFW window" << std::endl; 57 glfwTerminate(); 58 return -1; 59 } 60 glfwMakeContextCurrent(window); 61 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); 62 glfwSetCursorPosCallback(window, mouse_callback); 63 glfwSetScrollCallback(window, scroll_callback); 64 65 // tell GLFW to capture our mouse 66 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); 67 68 // glad: load all OpenGL function pointers 69 // --------------------------------------- 70 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) 71 { 72 std::cout << "Failed to initialize GLAD" << std::endl; 73 return -1; 74 } 75 76 // configure global opengl state 77 // ----------------------------- 78 glEnable(GL_DEPTH_TEST); 79 80 // build and compile our shader zprogram 81 // ------------------------------------ 82 Shader lightingShader("colors.vs", "colors.fs"); 83 Shader lampShader("lamp.vs", "lamp.fs"); 84 85 // set up vertex data (and buffer(s)) and configure vertex attributes 86 // ------------------------------------------------------------------ 87 float vertices[] = { 88 // positions // normals // texture coords 89 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 90 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 91 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, 92 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, 93 -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 94 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 95 96 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 97 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 98 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 99 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 100 -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 101 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 102 103 -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 104 -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 105 -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 106 -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 107 -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 108 -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 109 110 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 111 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 112 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 113 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 114 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 115 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 116 117 -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 118 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 119 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 120 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 121 -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 122 -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 123 124 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 125 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 126 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 127 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 128 -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 129 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f 130 }; 131 132 unsigned int VBO, cubeVAO; 133 glGenVertexArrays(1, &cubeVAO); 134 glGenBuffers(1, &VBO); 135 136 glBindVertexArray(cubeVAO); 137 138 glBindBuffer(GL_ARRAY_BUFFER, VBO); 139 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 140 141 // position attribute 142 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); 143 glEnableVertexAttribArray(0); 144 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); 145 glEnableVertexAttribArray(1); 146 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); 147 glEnableVertexAttribArray(2); 148 149 unsigned int diffuseMap = loadTexture("container2.png"); 150 unsigned int specularMap = loadTexture("container2_specular.png"); 151 unsigned int emissionMap = loadTexture("matrix.jpg"); 152 //unsigned int specularMap = loadTexture("matrix.jpg"); 153 154 lightingShader.use(); 155 lightingShader.setInt("material.diffuse", 0); 156 lightingShader.setInt("material.specular", 1); 157 lightingShader.setInt("material.emission", 2); 158 159 unsigned int lightVAO; 160 glGenVertexArrays(1, &lightVAO); 161 glBindVertexArray(lightVAO); 162 // 只需要绑定VBO不用再次设置VBO的数据,因为箱子的VBO数据中已经包含了正确的立方体顶点数据 163 glBindBuffer(GL_ARRAY_BUFFER, VBO); 164 // 设置灯立方体的顶点属性(对我们的灯来说仅仅只有位置数据) 165 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); 166 glEnableVertexAttribArray(0); 167 168 169 // render loop 170 // ----------- 171 while (!glfwWindowShouldClose(window)) 172 { 173 float currentFrame = glfwGetTime(); 174 deltaTime = currentFrame - lastFrame; 175 lastFrame = currentFrame; 176 177 // input 178 // ----- 179 processInput(window); 180 181 // render 182 // ------ 183 glClearColor(0.1f, 0.1f, 0.1f, 1.0f); 184 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 185 186 // bind textures on corresponding texture units 187 glActiveTexture(GL_TEXTURE0); 188 glBindTexture(GL_TEXTURE_2D, diffuseMap); 189 glActiveTexture(GL_TEXTURE1); 190 glBindTexture(GL_TEXTURE_2D, specularMap); 191 glActiveTexture(GL_TEXTURE2); 192 glBindTexture(GL_TEXTURE_2D, emissionMap); 193 194 // activate shader 195 lightingShader.use(); 196 197 lightingShader.setVec3("viewPos", camera.Position); 198 199 //lightingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f); 200 lightingShader.setFloat("material.shininess", 64.0f); 201 202 lightingShader.setVec3("light.position", lightPos); 203 lightingShader.setVec3("light.ambient", 0.2f, 0.2f, 0.2f); 204 lightingShader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f); // 将光照调暗了一些以搭配场景 205 lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f); 206 207 // pass projection matrix to shader (note that in this case it could change every frame) 208 glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); 209 lightingShader.setMat4("projection", projection); 210 211 // camera/view transformation 212 glm::mat4 view = camera.GetViewMatrix(); 213 lightingShader.setMat4("view", view); 214 215 glm::mat4 model = glm::mat4(1.0); 216 lightingShader.setMat4("model", model); 217 218 // render boxes 219 glBindVertexArray(cubeVAO); 220 glDrawArrays(GL_TRIANGLES, 0, 36); 221 222 lampShader.use(); 223 lampShader.setMat4("projection", projection); 224 lampShader.setMat4("view", view); 225 model = glm::mat4(1.0f); 226 float r = 5.0f; 227 float x = sin(glfwGetTime())*r; 228 float z = cos(glfwGetTime())*r; 229 lightPos.x = x; lightPos.z = z; 230 model = glm::translate(model, lightPos); 231 model = glm::scale(model, glm::vec3(0.2f)); 232 lampShader.setMat4("model", model); 233 234 glBindVertexArray(lightVAO); 235 glDrawArrays(GL_TRIANGLES, 0, 36); 236 237 // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) 238 // ------------------------------------------------------------------------------- 239 glfwSwapBuffers(window); 240 glfwPollEvents(); 241 } 242 243 // optional: de-allocate all resources once they've outlived their purpose: 244 // ------------------------------------------------------------------------ 245 glDeleteVertexArrays(1, &cubeVAO); 246 glDeleteVertexArrays(1, &lightVAO); 247 glDeleteBuffers(1, &VBO); 248 249 // glfw: terminate, clearing all previously allocated GLFW resources. 250 // ------------------------------------------------------------------ 251 glfwTerminate(); 252 return 0; 253 } 254 255 // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly 256 // --------------------------------------------------------------------------------------------------------- 257 void processInput(GLFWwindow *window) 258 { 259 if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) 260 glfwSetWindowShouldClose(window, true); 261 262 if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) 263 camera.ProcessKeyboard(FORWARD, deltaTime); 264 if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) 265 camera.ProcessKeyboard(BACKWARD, deltaTime); 266 if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) 267 camera.ProcessKeyboard(LEFT, deltaTime); 268 if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) 269 camera.ProcessKeyboard(RIGHT, deltaTime); 270 } 271 272 // glfw: whenever the window size changed (by OS or user resize) this callback function executes 273 // --------------------------------------------------------------------------------------------- 274 void framebuffer_size_callback(GLFWwindow* window, int width, int height) 275 { 276 // make sure the viewport matches the new window dimensions; note that width and 277 // height will be significantly larger than specified on retina displays. 278 glViewport(0, 0, width, height); 279 } 280 281 void mouse_callback(GLFWwindow* window, double xpos, double ypos){ 282 if (firstMouse) 283 { 284 lastX = xpos; 285 lastY = ypos; 286 firstMouse = false; 287 } 288 289 float xoffset = xpos - lastX; 290 float yoffset = lastY - ypos; 291 //std::cout << ypos << std::endl; 292 lastX = xpos; 293 lastY = ypos; 294 295 camera.ProcessMouseMovement(xoffset, yoffset); 296 } 297 298 // glfw: whenever the mouse scroll wheel scrolls, this callback is called 299 // ---------------------------------------------------------------------- 300 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) 301 { 302 camera.ProcessMouseScroll(yoffset); 303 } 304 305 // utility function for loading a 2D texture from file 306 // --------------------------------------------------- 307 unsigned int loadTexture(char const * path) 308 { 309 unsigned int textureID; 310 glGenTextures(1, &textureID); 311 312 int width, height, nrComponents; 313 unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0); 314 if (data) 315 { 316 GLenum format; 317 if (nrComponents == 1) 318 format = GL_RED; 319 else if (nrComponents == 3) 320 format = GL_RGB; 321 else if (nrComponents == 4) 322 format = GL_RGBA; 323 324 glBindTexture(GL_TEXTURE_2D, textureID); 325 glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); 326 glGenerateMipmap(GL_TEXTURE_2D); 327 328 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 329 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 330 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 331 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 332 333 stbi_image_free(data); 334 } 335 else 336 { 337 std::cout << "Texture failed to load at path: " << path << std::endl; 338 stbi_image_free(data); 339 } 340 341 return textureID; 342 }
效果图:
2019/11/30