9 Application::Application()
14 , ctx(window.CreateContext())
17 , move_velocity(0.003f)
18 , pitch_sensitivity(-0.0025f)
19 , yaw_sensitivity(-0.001f)
23 { 0.0f, 0.0f, 1.0f }, // front, red
29 { 0.0f, 0.0f, 0.0f }, // back, cyan
35 { 0.0f, 1.0f, 0.0f }, // top, green
41 { 0.0f, 0.0f, 0.0f }, // bottom, magenta
47 { 0.0f, 0.0f, 0.0f }, // left, blue
53 { 1.0f, 0.0f, 0.0f }, // right, yellow
61 { 1.0f, 0.0f, 0.0f }, // front, red
67 { 0.0f, 1.0f, 1.0f }, // back, cyan
73 { 0.0f, 1.0f, 0.0f }, // top, green
79 { 1.0f, 0.0f, 1.0f }, // bottom, magenta
85 { 0.0f, 0.0f, 1.0f }, // left, blue
91 { 1.0f, 1.0f, 0.0f }, // right, yellow
99 { 0.0f, 0.0f, 1.0f }, // front, red
100 { 0.0f, 0.0f, 1.0f },
101 { 0.0f, 0.0f, 1.0f },
102 { 0.0f, 0.0f, 1.0f },
103 { 0.0f, 0.0f, 1.0f },
104 { 0.0f, 0.0f, 1.0f },
105 { 0.0f, 0.0f, -1.0f }, // back, cyan
106 { 0.0f, 0.0f, -1.0f },
107 { 0.0f, 0.0f, -1.0f },
108 { 0.0f, 0.0f, -1.0f },
109 { 0.0f, 0.0f, -1.0f },
110 { 0.0f, 0.0f, -1.0f },
111 { 0.0f, 1.0f, 0.0f }, // top, green
112 { 0.0f, 1.0f, 0.0f },
113 { 0.0f, 1.0f, 0.0f },
114 { 0.0f, 1.0f, 0.0f },
115 { 0.0f, 1.0f, 0.0f },
116 { 0.0f, 1.0f, 0.0f },
117 { 0.0f, -1.0f, 0.0f }, // bottom, magenta
118 { 0.0f, -1.0f, 0.0f },
119 { 0.0f, -1.0f, 0.0f },
120 { 0.0f, -1.0f, 0.0f },
121 { 0.0f, -1.0f, 0.0f },
122 { 0.0f, -1.0f, 0.0f },
123 { -1.0f, 0.0f, 0.0f }, // left, blue
124 { -1.0f, 0.0f, 0.0f },
125 { -1.0f, 0.0f, 0.0f },
126 { -1.0f, 0.0f, 0.0f },
127 { -1.0f, 0.0f, 0.0f },
128 { -1.0f, 0.0f, 0.0f },
129 { 1.0f, 0.0f, 0.0f }, // right, yellow
130 { 1.0f, 0.0f, 0.0f },
131 { 1.0f, 0.0f, 0.0f },
132 { 1.0f, 0.0f, 0.0f },
133 { 1.0f, 0.0f, 0.0f },
134 { 1.0f, 0.0f, 0.0f },
137 , light_position(5.0f, 5.0f, 5.0f)
138 , light_color(1.0f, 1.0f, 1.0f)
144 , light_position_handle(0)
145 , light_color_handle(0)
146 , light_power_handle(0)
154 GLContext::EnableVSync();
155 GLContext::EnableBackfaceCulling();
158 "#version 330 core\n"
159 "layout(location = 0) in vec3 vtx_position;\n"
160 "layout(location = 1) in vec3 vtx_color;\n"
161 "layout(location = 2) in vec3 vtx_normal;\n"
164 "uniform mat4 MVP;\n"
165 "uniform vec3 light_position;\n"
166 "out vec3 frag_color;\n"
167 "out vec3 vtx_world;\n"
170 "out vec3 light_direction;\n"
172 "vec4 v = vec4(vtx_position, 1);\n"
173 "gl_Position = MVP * v;\n"
174 "vtx_world = (M * v).xyz;\n"
175 "vec3 vtx_camera = (V * M * v).xyz;\n"
176 "eye = vec3(0, 0, 0) - vtx_camera;\n"
177 "vec3 light_camera = (V * v).xyz;\n"
178 "light_direction = light_position + eye;\n"
179 "normal = (V * M * vec4(vtx_normal, 0)).xyz;\n"
180 "frag_color = vtx_color;\n"
185 "#version 330 core\n"
186 "in vec3 frag_color;\n"
187 "in vec3 vtx_world;\n"
190 "in vec3 light_direction;\n"
192 "uniform vec3 light_position;\n"
193 "uniform vec3 light_color;\n"
194 "uniform float light_power;\n"
197 "vec3 ambient = vec3(0.1, 0.1, 0.1) * frag_color;\n"
198 "vec3 specular = vec3(0.3, 0.3, 0.3);\n"
199 "float distance = length(light_position - vtx_world);\n"
200 "vec3 n = normalize(normal);\n"
201 "vec3 l = normalize(light_direction);\n"
202 "float cos_theta = clamp(dot(n, l), 0, 1);\n"
203 "vec3 E = normalize(eye);\n"
204 "vec3 R = reflect(-l, n);\n"
205 "float cos_alpha = clamp(dot(E, R), 0, 1);\n"
207 " + frag_color * light_color * light_power * cos_theta / (distance * distance)"
208 " + specular * light_color * light_power * pow(cos_alpha, 5) / (distance * distance);\n"
212 if (!program.Linked()) {
213 program.Log(std::cerr);
214 throw std::runtime_error("link program");
217 GLuint VertexArrayID;
218 glGenVertexArrays(1, &VertexArrayID);
219 glBindVertexArray(VertexArrayID);
221 modelCtrl.Position(glm::vec3(0, 0, -4));
222 cam.Position(glm::vec3(0, 0, 4));
224 m_handle = program.UniformLocation("M");
225 v_handle = program.UniformLocation("V");
226 mv_handle = program.UniformLocation("MV");
227 mvp_handle = program.UniformLocation("MVP");
228 light_position_handle = program.UniformLocation("light_position");
229 light_color_handle = program.UniformLocation("light_color");
230 light_power_handle = program.UniformLocation("light_power");
232 glClearColor(0.0, 0.0, 0.0, 1.0);
235 Application::~Application() {
240 void Application::Run() {
242 Uint32 last = SDL_GetTicks();
245 Uint32 now = SDL_GetTicks();
246 int delta = now - last;
252 void Application::Loop(int dt) {
259 void Application::HandleEvents() {
261 while (SDL_PollEvent(&event)) {
262 switch (event.type) {
265 switch (event.key.keysym.sym) {
267 front = event.key.state == SDL_PRESSED;
270 back = event.key.state == SDL_PRESSED;
273 left = event.key.state == SDL_PRESSED;
276 right = event.key.state == SDL_PRESSED;
279 up = event.key.state == SDL_PRESSED;
282 down = event.key.state == SDL_PRESSED;
286 case SDL_MOUSEMOTION:
287 cam.RotateYaw(event.motion.xrel * yaw_sensitivity);
288 cam.RotatePitch(event.motion.yrel * pitch_sensitivity);
293 case SDL_WINDOWEVENT:
294 switch (event.window.event) {
295 case SDL_WINDOWEVENT_RESIZED:
296 cam.Viewport(event.window.data1, event.window.data2);
308 void Application::Update(int dt) {
310 if (right && !left) {
311 vel.x = move_velocity;
312 } else if (left && !right) {
313 vel.x = -move_velocity;
316 vel.y = move_velocity;
317 } else if (down && !up) {
318 vel.y = -move_velocity;
320 if (back && !front) {
321 vel.z = move_velocity;
322 } else if (front && !back) {
323 vel.z = -move_velocity;
325 cam.OrientationVelocity(vel);
328 modelCtrl.Update(dt);
331 void Application::Render() {
332 glClear(GL_COLOR_BUFFER_BIT);
336 glm::mat4 m(modelCtrl.Transform());
337 glm::mat4 mv(cam.View() * m);
338 glm::mat4 mvp(cam.MakeMVP(m));
339 glUniformMatrix4fv(m_handle, 1, GL_FALSE, &m[0][0]);
340 glUniformMatrix4fv(v_handle, 1, GL_FALSE, &cam.View()[0][0]);
341 glUniformMatrix4fv(mv_handle, 1, GL_FALSE, &mv[0][0]);
342 glUniformMatrix4fv(mvp_handle, 1, GL_FALSE, &mvp[0][0]);
343 glUniform3f(light_position_handle, light_position.x, light_position.y, light_position.z);
344 glUniform3f(light_color_handle, light_color.x, light_color.y, light_color.z);
345 glUniform1f(light_power_handle, light_power);