-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
330 lines (263 loc) · 11.5 KB
/
main.cpp
File metadata and controls
330 lines (263 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#include "Angel.h"
#include "TriMesh.h"
#include "Camera.h"
#include <vector>
#include <string>
int WIDTH = 600;
int HEIGHT = 600;
int mainWindow;
struct openGLObject {
// 顶点数组对象
GLuint vao;
// 顶点缓存对象
GLuint vbo;
// 着色器程序
GLuint program;
// 着色器文件
std::string vshader;
std::string fshader;
// 着色器变量
GLuint pLocation;
GLuint cLocation;
// 投影变换变量
GLuint modelLocation;
GLuint viewLocation;
GLuint projectionLocation;
// 阴影变量
GLboolean shadowLocation;
};
// 全局变量光源位置
glm::vec3 light_position = glm::vec3(0.0, 1.5, 1.0);
// 全局变量键盘控制光源移动的参数
float move_step_size = 0.2;
openGLObject tri_object;
openGLObject plane_object;
openGLObject cube_object;
TriMesh *triangle = new TriMesh();
TriMesh *plane = new TriMesh();
Camera *camera = new Camera();
TriMesh *cube = new TriMesh();
void bindObjectAndData(TriMesh *mesh, openGLObject &object, const std::string &vshader, const std::string &fshader) {
// 创建顶点数组对象
glGenVertexArrays(1, &object.vao);
glBindVertexArray(object.vao);
// 创建并初始化顶点缓存对象
glGenBuffers(1, &object.vbo);
glBindBuffer(GL_ARRAY_BUFFER, object.vbo);
glBufferData(GL_ARRAY_BUFFER,
mesh->getPoints().size() * sizeof(glm::vec3) + mesh->getColors().size() * sizeof(glm::vec3),
NULL,
GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, mesh->getPoints().size() * sizeof(glm::vec3), &mesh->getPoints()[0]);
glBufferSubData(GL_ARRAY_BUFFER, mesh->getPoints().size() * sizeof(glm::vec3),
mesh->getColors().size() * sizeof(glm::vec3), &mesh->getColors()[0]);
object.vshader = vshader;
object.fshader = fshader;
object.program = InitShader(object.vshader.c_str(), object.fshader.c_str());
// 从顶点着色器中初始化顶点的位置
object.pLocation = glGetAttribLocation(object.program, "vPosition");
glEnableVertexAttribArray(object.pLocation);
glVertexAttribPointer(object.pLocation, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
// 从顶点着色器中初始化顶点的颜色
object.cLocation = glGetAttribLocation(object.program, "vColor");
glEnableVertexAttribArray(object.cLocation);
glVertexAttribPointer(object.cLocation, 3, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(mesh->getPoints().size() * sizeof(glm::vec3)));
// 获得矩阵位置
object.modelLocation = glGetUniformLocation(object.program, "model");
object.viewLocation = glGetUniformLocation(object.program, "view");
object.projectionLocation = glGetUniformLocation(object.program, "projection");
// 获得阴影标识的位置
object.shadowLocation = glGetUniformLocation(object.program, "isShadow");
}
void framebuffer_size_callback(GLFWwindow *window, int width, int height) {
glViewport(0, 0, width, height);
}
void init() {
std::string vshader, fshader;
// 读取着色器并使用
vshader = "shaders/vshader.glsl";
fshader = "shaders/fshader.glsl";
// 创建三角形,颜色设置为红色
triangle->generateTriangle(glm::vec3(1.0, 0.0, 0.0));
// 设置三角形的位置和旋转
triangle->setRotation(glm::vec3(90, 0, 0));
triangle->setTranslation(glm::vec3(0, 0.3, 0));
triangle->setScale(glm::vec3(0.5, 0.5, 0.5));
bindObjectAndData(triangle, tri_object, vshader, fshader);
// 创建正方形平面,设置为黄绿色
plane->generateSquare(glm::vec3(0.6, 0.8, 0.0));
// 设置正方形的位置和旋转,注意这里我们将正方形平面下移了一点点距离,
// 这是为了防止和阴影三角形重叠在同个平面上导致颜色交叉
plane->setRotation(glm::vec3(90, 0, 0));
plane->setTranslation(glm::vec3(0, -0.001, 0));
plane->setScale(glm::vec3(3, 3, 3));
bindObjectAndData(plane, plane_object, vshader, fshader);
std::string lv, lf;
lv = "shaders/lightv.glsl";
lf = "shaders/lightf.glsl";
cube->generateCube();
bindObjectAndData(cube, cube_object, lv, lf);
glClearColor(1.0, 1.0, 1.0, 1.0);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera->updateCamera();
// 计算视图变换矩阵
camera->viewMatrix = camera->getViewMatrix();
// 计算相机投影矩阵
camera->projMatrix = camera->getProjectionMatrix(true);
// 绘制三角形
glBindVertexArray(tri_object.vao);
glUseProgram(tri_object.program);
// 三角形物体的变换矩阵,注意初始三角形是与Z轴垂直的
glm::mat4 modelMatrix = triangle->getModelMatrix();
// 传递投影变换矩阵
glUniformMatrix4fv(tri_object.modelLocation, 1, GL_FALSE, &modelMatrix[0][0]);
glUniformMatrix4fv(tri_object.viewLocation, 1, GL_FALSE, &camera->viewMatrix[0][0]);
glUniformMatrix4fv(tri_object.projectionLocation, 1, GL_FALSE, &camera->projMatrix[0][0]);
// 将isShadow设置为1,表示正常绘制的颜色,如果是0则表示阴影
glUniform1i(tri_object.shadowLocation, 1);
glDrawArrays(GL_TRIANGLES, 0, triangle->getPoints().size());
float radius = 1.0f;
light_position.x = radius * sin(glfwGetTime());
light_position.z = radius * cos(glfwGetTime());
// 绘制三角形阴影
// @TODO: Task2:根据光源位置,计算阴影投影矩阵
// 计算阴影的模型变换矩阵。
float lx = light_position[0], ly = light_position[1], lz = light_position[2];
glm::mat4 shadow = glm::mat4(0.0);
shadow[0][0] = -light_position.y, shadow[0][1] = light_position.x;
shadow[1] = glm::vec4(0.0);
shadow[2][1] = light_position.z, shadow[2][2] = -light_position.y;
shadow[3][1] = 1, shadow[3][3] = -light_position.y;
shadow = glm::transpose(shadow) * modelMatrix;
// 传递 isShadow 变量。
glUniform1i(tri_object.shadowLocation, 0);
// 传递 unifrom 关键字的矩阵数据。
glUniformMatrix4fv(tri_object.modelLocation, 1, GL_FALSE, &shadow[0][0]);
// 绘制
glDrawArrays(GL_TRIANGLES, 0, triangle->getPoints().size());
// 绘制平面
glBindVertexArray(plane_object.vao);
glUseProgram(plane_object.program);
modelMatrix = plane->getModelMatrix();
glUniformMatrix4fv(plane_object.modelLocation, 1, GL_FALSE, &modelMatrix[0][0]);
glUniformMatrix4fv(plane_object.viewLocation, 1, GL_FALSE, &camera->viewMatrix[0][0]);
glUniformMatrix4fv(plane_object.projectionLocation, 1, GL_FALSE, &camera->projMatrix[0][0]);
// 将isShadow设置为1,表示正常绘制的颜色,如果是0则表示阴影
glUniform1i(plane_object.shadowLocation, 1);
glDrawArrays(GL_TRIANGLES, 0, plane->getPoints().size());
// 绘制cube
glBindVertexArray(cube_object.vao);
glUseProgram(cube_object.program);
glm::mat4 cubeModel = glm::mat4(1.0);
cubeModel = glm::translate(cubeModel, glm::vec3(light_position));
cubeModel = glm::scale(cubeModel, glm::vec3(0.2, 0.2, 0.2));
glUniformMatrix4fv(cube_object.modelLocation, 1, GL_FALSE, &cubeModel[0][0]);
glUniformMatrix4fv(cube_object.viewLocation, 1, GL_FALSE, &camera->viewMatrix[0][0]);
glUniformMatrix4fv(cube_object.projectionLocation, 1, GL_FALSE, &camera->projMatrix[0][0]);
glDrawArrays(GL_TRIANGLES, 0, cube->getPoints().size());
}
void printHelp() {
std::cout << "Keyboard Usage" << std::endl;
std::cout <<
"[Window]" << std::endl <<
"ESC: Exit" << std::endl <<
"h: Print help message" << std::endl <<
std::endl <<
"[Light]" << std::endl <<
"r: Reset light parameters" << std::endl <<
"x/(shift+x): move the light along X positive/negative axis" << std::endl <<
"y/(shift+y): move the light along Y positive/negative axis" << std::endl <<
"z/(shift+z): move the light along Z positive/negative axis" << std::endl <<
"a/(shift+a): Increase/Decrease move_step_size" << std::endl <<
std::endl <<
"[Camera]" << std::endl <<
"SPACE: Reset camera parameters" << std::endl <<
"u/(shift+u): Increase/Decrease the rotate angle" << std::endl <<
"i/(shift+i): Increase/Decrease the up angle" << std::endl <<
"o/(shift+o): Increase/Decrease the scale" << std::endl;
}
void mainWindow_key_callback(GLFWwindow *window, int key, int scancode, int action, int mode) {
// 'ESC键退出'
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
} else if (key == GLFW_KEY_H && action == GLFW_PRESS) {
printHelp();
} else if (key == GLFW_KEY_R && action == GLFW_PRESS) {
light_position = glm::vec3(0.0, 1.5, 1.0);
move_step_size = 0.2;
} else if (key == GLFW_KEY_X && action == GLFW_PRESS && mode == 0x0000) {
light_position[0] += move_step_size;
} else if (key == GLFW_KEY_X && action == GLFW_PRESS && mode == GLFW_MOD_SHIFT) {
light_position[0] -= move_step_size;
} else if (key == GLFW_KEY_Y && action == GLFW_PRESS && mode == 0x0000) {
light_position[1] += move_step_size;
} else if (key == GLFW_KEY_Y && action == GLFW_PRESS && mode == GLFW_MOD_SHIFT) {
light_position[1] -= move_step_size;
if (light_position[1] <= 1.0) {
light_position[1] += move_step_size;
}
} else if (key == GLFW_KEY_Z && action == GLFW_PRESS && mode == 0x0000) {
light_position[2] += move_step_size;
} else if (key == GLFW_KEY_Z && action == GLFW_PRESS && mode == GLFW_MOD_SHIFT) {
light_position[2] -= move_step_size;
} else if (key == GLFW_KEY_A && action == GLFW_PRESS && mode == 0x0000) {
move_step_size += 0.1;
} else if (key == GLFW_KEY_A && action == GLFW_PRESS && mode == GLFW_MOD_SHIFT) {
move_step_size -= 0.1;
} else {
camera->keyboard(key, action, mode);
}
}
void cleanData() {
triangle->cleanData();
plane->cleanData();
delete camera;
camera = NULL;
// 释放内存
delete triangle;
triangle = NULL;
delete plane;
plane = NULL;
// 删除绑定的对象
glDeleteVertexArrays(1, &tri_object.vao);
glDeleteVertexArrays(1, &plane_object.vao);
glDeleteBuffers(1, &tri_object.vbo);
glDeleteProgram(tri_object.program);
glDeleteBuffers(1, &plane_object.vbo);
glDeleteProgram(plane_object.program);
}
int main(int argc, char **argv) {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
GLFWwindow *mainwindow = glfwCreateWindow(600, 600, "Hard Shadow", NULL, NULL);
if (mainwindow == NULL) {
std::cout << "Failed to create GLFW window!" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(mainwindow);
glfwSetFramebufferSizeCallback(mainwindow, framebuffer_size_callback);
glfwSetKeyCallback(mainwindow, mainWindow_key_callback);
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);
init();
printHelp();
while (!glfwWindowShouldClose(mainwindow)) {
display();
glfwSwapBuffers(mainwindow);
glfwPollEvents();
}
glfwTerminate();
return 0;
}