添加一个叫做放射光贴图(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
