Reflection
[opengl.git] / main.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <iostream>
4 #include <array>
5 #include <vector>
6 #ifdef __APPLE__
7 #include <GL/glew.h>
8 #else
9 #include <OpenGL/glew.h>
10 #endif
11 #include <GLUT/glut.h>
12 #include "shapes.hpp"
13 #include <glm/glm.hpp>
14 #include <glm/ext.hpp>
15 #include <glm/gtc/type_ptr.hpp>
16 #include "model.hpp"
17 #include "program.hpp"
18 #include "skybox.hpp"
19
20 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
21
22 using namespace std;
23
24 GLuint lightVao;
25
26 Program *textureProg, *plainProg, *reflectProg;
27 Skybox *skybox;
28                           
29 glm::vec3 camPos   = glm::vec3(0.0f, 0.0f,  0.0f);
30 glm::vec3 camFront = glm::vec3(0.0f, 0.0f, 1.0f);
31 glm::vec3 camUp    = glm::vec3(0.0f, 1.0f,  0.0f);
32 float yaw = 1.57, pitch = 0;
33 bool doScale, doRotate, doTranslate;
34 Model *chest, *mirrorCube;
35 glm::vec3 lightPos(3);
36
37 const int WIDTH = 800, HEIGHT = 600;
38 const float ASPECT = (float)WIDTH / (float)HEIGHT;
39
40 glm::mat4 projMat() {
41         return glm::perspective(glm::radians(45.f), ASPECT, 0.01f, 10000.f);
42 }
43
44 glm::mat4 viewMat() {
45         return glm::lookAt(camPos, camPos + camFront, camUp);
46 }
47
48 void setProjectionAndViewUniforms(GLuint progId) {
49         GLuint projLoc = glGetUniformLocation(progId, "projection");
50         glm::mat4 proj = projMat();
51         glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));
52
53         GLuint viewLoc = glGetUniformLocation(progId, "view");
54         glm::mat4 view = viewMat();
55         glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
56 }
57
58 void setLightColorAndPos(GLuint progId, glm::vec3 lightPos, glm::vec4 lightColor) {
59         GLuint lightColorLoc = glGetUniformLocation(progId, "lightColor");
60         glUniform4fv(lightColorLoc, 1, glm::value_ptr(lightColor));
61
62         GLuint lightPosLoc = glGetUniformLocation(progId, "vLightPos");
63         glUniform3fv(lightPosLoc, 1, glm::value_ptr(lightPos));
64
65         GLuint viewPosLoc = glGetUniformLocation(progId, "vViewPos");
66         glUniform3fv(viewPosLoc, 1, glm::value_ptr(camPos));
67 }
68
69 void drawLight(float d, glm::vec3 lightPos, glm::vec4 lightColor) {
70         glUseProgram(plainProg->progId);
71         glBindVertexArray(lightVao);
72         setProjectionAndViewUniforms(plainProg->progId);
73         glm::mat4 model = glm::translate(glm::mat4(1.f), lightPos);
74         model = glm::scale(model, glm::vec3(0.2));
75         GLuint modelLoc = glGetUniformLocation(plainProg->progId, "model");
76         glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
77
78         GLuint colorLoc = glGetUniformLocation(plainProg->progId, "color");
79         glm::vec4 color(lightColor);
80         glUniform4fv(colorLoc, 1, glm::value_ptr(color));
81                 
82         glDrawArrays(GL_TRIANGLES, 0, 36);
83 }
84
85
86 void display() {
87         glClearColor(0.5, 0.5, 0.5, 1);
88         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
89         float d = (float)glutGet(GLUT_ELAPSED_TIME) * 0.001f;
90
91         glm::vec4 lightColor(1, 1, 1, 1);
92
93         drawLight(d, lightPos, lightColor);
94
95         glUseProgram(textureProg->progId);
96         setProjectionAndViewUniforms(textureProg->progId);
97         setLightColorAndPos(textureProg->progId, lightPos, lightColor);
98
99         /* Model::Node *top = chest->find("top"); */
100         /* top->model = glm::translate(glm::mat4(1), glm::vec3(0, 1, -1)); */
101         /* top->model = glm::rotate(top->model, sin(d / 2.5f) * 0.5f, glm::vec3(1, 0, 0)); */
102         /* top->model = glm::translate(top->model, glm::vec3(0, -1, 1)); */
103         
104         /* Model::Node *jewels = chest->find("jewels"); */
105         /* jewels->model = glm::scale(glm::mat4(1), glm::vec3((sin(d) + 1.2f) / 2.f)); */
106
107         /* Model::Node *lock = chest->find("lock"); */
108         /* lock->model = glm::translate(glm::mat4(1), glm::vec3(0.22610, 3.36478, -0.75649)); */
109         /* lock->model = glm::rotate(lock->model, (d / 2.5f), glm::vec3(0, 1, 0.4)); */
110         /* lock->model = glm::translate(lock->model, -glm::vec3(0.22610, 3.36478, -0.75649)); */
111
112         /* Model::Node *key = chest->find("key"); */
113         /* key->model = glm::translate(glm::mat4(1), glm::vec3(0, 0, sin(d))); */
114         
115         /* chest->draw(); */
116
117         mirrorCube->draw();
118
119         skybox->draw(projMat(), viewMat());
120
121         glutSwapBuffers();
122 }
123
124 void setupLightBuffers(GLuint progId) {
125         auto vertices = cube();
126         GLuint verticesSize = 36 * 3 * sizeof(GLfloat);
127
128         glGenVertexArrays(1, &lightVao);
129         GLuint vbo;
130         glBindVertexArray(lightVao);
131         glGenBuffers(1, &vbo);
132         glBindBuffer(GL_ARRAY_BUFFER, vbo);
133         glBufferData(GL_ARRAY_BUFFER, verticesSize, NULL, GL_STATIC_DRAW);
134         glBufferSubData(GL_ARRAY_BUFFER, 0, verticesSize, glm::value_ptr(vertices[0]));
135         GLuint posLoc = glGetAttribLocation(progId, "vPosition");
136         glEnableVertexAttribArray(posLoc);
137         glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
138 }
139
140 void init() {
141         plainProg = new Program("plainvertex.glsl", "plainfrag.glsl");
142         glUseProgram(plainProg->progId);
143         setupLightBuffers(plainProg->progId);
144         plainProg->validate();
145
146         std::vector<std::string> faces = {
147                 "models/skybox/right.jpg",
148                 "models/skybox/left.jpg",
149                 "models/skybox/top.jpg",
150                 "models/skybox/bottom.jpg",
151                 "models/skybox/front.jpg",
152                 "models/skybox/back.jpg"
153         };
154         skybox = new Skybox(faces);
155
156         textureProg = new Program("texturevertex.glsl", "texturefrag.glsl");
157         /* chest = new Model("models/chest.dae", *textureProg, *skybox); */
158
159         mirrorCube = new Model("models/mirrorCube.dae", *textureProg, *skybox);
160
161         glEnable(GL_DEPTH_TEST); 
162         glEnable(GL_CULL_FACE); 
163 }
164
165 bool* keyStates = new bool[256];
166
167 void keyboard(unsigned char key, int x, int y) {
168         keyStates[key] = true;
169         if (key == 'z')
170                 doScale = !doScale;
171         if (key == 'x')
172                 doRotate = !doRotate;
173         if (key == 'c')
174                 doTranslate = !doTranslate;
175 }
176
177 void keyboardUp(unsigned char key, int x, int y) {
178         keyStates[key] = false;
179 }
180
181 void timer(int _) {
182         float xSpeed = 0.f, ySpeed = 0.f, zSpeed = 0.f;
183         if (keyStates['w'])
184                 zSpeed = 0.1f;
185         if (keyStates['s'])
186                 zSpeed = -0.1f;
187         if (keyStates['a'])
188                 xSpeed = 0.1f;
189         if (keyStates['d'])
190                 xSpeed = -0.1f;
191         if (keyStates['q'])
192                 ySpeed = 0.1f;
193         if (keyStates['e'])
194                 ySpeed = -0.1f;
195
196         if (keyStates['j']) lightPos.z += 0.1f;
197         if (keyStates['k']) lightPos.z -= 0.1f;
198         if (keyStates['h']) lightPos.x -= 0.1f;
199         if (keyStates['l']) lightPos.x += 0.1f;
200         if (keyStates['m']) lightPos.y -= 0.1f;
201         if (keyStates['n']) lightPos.y += 0.1f;
202
203         camPos.x += xSpeed * sin(yaw) + zSpeed * cos(yaw);
204         camPos.y += ySpeed;
205         camPos.z += zSpeed * sin(yaw) - xSpeed * cos(yaw);
206         glutPostRedisplay();
207         glutTimerFunc(16, timer, 0);
208 }
209
210 int prevMouseX, prevMouseY;
211 bool firstMouse = true;
212
213 void motion(int x, int y) {
214         if (firstMouse) {
215                 prevMouseX = x;
216                 prevMouseY = y;
217                 firstMouse = false;
218         }
219         int dx = x - prevMouseX, dy = y - prevMouseY;
220
221         prevMouseX = x;
222         prevMouseY = y;
223
224         const float sensitivity = 0.005f;
225         yaw += dx * sensitivity;
226         pitch -= dy * sensitivity;
227
228         glm::vec3 front;
229         front.x = cos(pitch) * cos(yaw);
230         front.y = sin(pitch);
231         front.z = cos(pitch) * sin(yaw);
232         camFront = glm::normalize(front);
233
234         if (pitch < -1.57079632679 || pitch >= 1.57079632679) {
235                 camUp = glm::vec3(0, -1, 0);
236         } else {
237                 camUp = glm::vec3(0, 1, 0);
238         }
239 }
240
241 void mouse(int button, int state, int x, int y) {
242         if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
243                 firstMouse = true;
244 }
245
246 int main(int argc, char** argv) {
247         glutInit(&argc, argv);
248         glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGB|GLUT_3_2_CORE_PROFILE);
249         glutInitWindowSize(WIDTH, HEIGHT);
250         int win = glutCreateWindow("Hello Triangle");
251         glutDisplayFunc(display);
252
253         glewInit();
254         
255         init();
256
257         glutKeyboardFunc(keyboard);
258         glutKeyboardUpFunc(keyboardUp);
259         glutTimerFunc(16, timer, 0);
260         glutMotionFunc(motion);
261         glutMouseFunc(mouse);
262
263         glutMainLoop();
264
265         return 0;
266 }
267