11 #include <OpenGL/glew.h>
13 #include <GLUT/glut.h>
14 #include <glm/glm.hpp>
15 #include <glm/ext.hpp>
16 #include <glm/gtc/type_ptr.hpp>
18 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
24 glm::vec3 camPos = glm::vec3(0.0f, 0.0f, -5.0f);
25 glm::vec3 camFront = glm::vec3(0.0f, 0.0f, 1.0f);
26 glm::vec3 camUp = glm::vec3(0.0f, 1.0f, 0.0f);
27 float yaw = 1.57, pitch = 0;
28 bool doScale, doRotate, doTranslate;
31 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
33 glBindVertexArray(vaos[0]);
35 float d = (float)glutGet(GLUT_ELAPSED_TIME) * 0.001f;
37 GLuint projId = glGetUniformLocation(progId, "projection");
38 glm::mat4 proj = glm::perspective(glm::radians(45.f), 1.33f, 0.01f, 10000.f);
39 glUniformMatrix4fv(projId, 1, GL_FALSE, glm::value_ptr(proj));
41 GLuint viewId = glGetUniformLocation(progId, "view");
42 glm::mat4 view = glm::lookAt(camPos, camPos + camFront, camUp);
43 glUniformMatrix4fv(viewId, 1, GL_FALSE, glm::value_ptr(view));
45 GLuint lightPosLoc = glGetUniformLocation(progId, "lightPos");
46 glm::vec3 lightPos = glm::vec3(sin(d) * 10, 0, 0);//10 * cos(d));
47 glUniform3fv(lightPosLoc, 1, glm::value_ptr(lightPos));
49 GLuint viewPosLoc = glGetUniformLocation(progId, "viewPos");
50 glUniform3fv(viewPosLoc, 1, glm::value_ptr(camPos));
52 GLuint modelId = glGetUniformLocation(progId, "model");
54 for (int i = 0; i < 10; i++) {
56 glm::mat4 model = glm::mat4(1.f);
58 model = glm::translate(model, glm::vec3(sin(i * 30) * 10, 0, i * 2 - 10));
61 model = glm::rotate(model, d * glm::radians(30.f), glm::vec3(0.f, 1.f, 0.f));
62 model = glm::rotate(model, d * glm::radians(20.f), glm::vec3(1.f, 0.f, 0.f));
66 model = glm::scale(model, glm::vec3(1.f, 0.7f + 0.7f * (1 + sin(d + (i + 3))), 1.f));
69 model = glm::translate(model, glm::vec3(sin(d + (i + 1)), cos(d + (i + -3)), sin(d + (i + 4))));
72 glUniformMatrix4fv(modelId, 1, GL_FALSE, glm::value_ptr(model));
74 glDrawArrays(GL_TRIANGLES, 0, 12);
79 void attachShader(GLuint progId, const char* filePath, GLenum type) {
80 GLuint shader = glCreateShader(type);
83 fprintf(stderr, "error creating shader\n");
87 ifstream file(filePath);
89 buffer << file.rdbuf();
90 string str = buffer.str();
91 const char* contents = str.c_str();
93 glShaderSource(shader, 1, (const GLchar**)&contents, NULL);
94 glCompileShader(shader);
96 glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
99 glGetShaderInfoLog(shader, 1024, NULL, log);
100 fprintf(stderr, "error: %s\n", log);
103 glAttachShader(progId, shader);
106 GLuint compileShaders(char* vertexShader, char* fragmentShader) {
107 GLuint progId = glCreateProgram();
109 attachShader(progId, vertexShader, GL_VERTEX_SHADER);
110 attachShader(progId, fragmentShader, GL_FRAGMENT_SHADER);
112 glLinkProgram(progId);
114 glGetProgramiv(progId, GL_LINK_STATUS, &success);
117 glGetProgramInfoLog(progId, sizeof(log), NULL, log);
118 fprintf(stderr, "error linking: %s\n", log);
125 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
127 GLuint setupBuffers(glm::vec3* vertices, glm::vec3* normals, GLuint progId) {
147 GLuint numVerts = 12;
150 glGenBuffers(1, &vbo);
153 glGenVertexArrays(1, &vao);
155 GLuint posId = glGetAttribLocation(progId, "vPosition");
156 GLuint colorId = glGetAttribLocation(progId, "vColor");
157 GLuint normalLoc = glGetAttribLocation(progId, "vNormal");
159 GLuint vertsLen = numVerts * 3 * sizeof(GLfloat);
160 GLuint colorsLen = numVerts * 4 * sizeof(GLfloat);
161 GLuint normalLen = numVerts * 3 * sizeof(GLfloat);
163 glBindBuffer(GL_ARRAY_BUFFER, vbo);
164 glBufferData(GL_ARRAY_BUFFER, vertsLen + colorsLen + normalLen, NULL, GL_STATIC_DRAW);
166 glBufferSubData(GL_ARRAY_BUFFER, 0, vertsLen, glm::value_ptr(vertices[0]));
167 glBufferSubData(GL_ARRAY_BUFFER, vertsLen, colorsLen, colors);
168 glBufferSubData(GL_ARRAY_BUFFER, vertsLen + colorsLen, normalLen, glm::value_ptr(normals[0]));
170 glBindVertexArray(vao);
172 glEnableVertexAttribArray(posId);
173 glVertexAttribPointer(posId, 3, GL_FLOAT, GL_FALSE, 0, 0);
175 glEnableVertexAttribArray(colorId);
176 glVertexAttribPointer(colorId, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(vertsLen));
178 glEnableVertexAttribArray(normalLoc);
179 glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(vertsLen + colorsLen));
184 void validateProgram(GLuint progId) {
185 glValidateProgram(progId);
188 glGetProgramiv(progId, GL_VALIDATE_STATUS, &success);
191 glGetProgramInfoLog(progId, sizeof(log), NULL, log);
192 fprintf(stderr, "error: %s\n", log);
198 glm::vec3 vertices[12] = {
199 glm::vec3(0.0f, 1.0f, 0.0f),
200 glm::vec3(1.0f, -1.0f, -1.0f),
201 glm::vec3(-1.0f, -1.0f, -1.0f),
203 glm::vec3(0.0f, 1.0f, 0.0f),
204 glm::vec3(-1.0f, -1.0f, 1.0f),
205 glm::vec3(1.0f, -1.0f, 1.0f),
207 glm::vec3(0.0f, 1.0f, 0.0f),
208 glm::vec3(-1.0f, -1.0f, -1.0f),
209 glm::vec3(-1.0f, -1.0f, 1.0f),
211 glm::vec3(0.0f, 1.0f, 0.0f),
212 glm::vec3(1.0f, -1.0f, 1.0f),
213 glm::vec3(1.0f, -1.0f, -1.0f)
216 // work out the normals
217 glm::vec3 normals[12];
218 for (int i = 0; i < 4; i++) {
219 glm::vec3 a = vertices[i * 3];
220 glm::vec3 b = vertices[i * 3 + 1];
221 glm::vec3 c = vertices[i * 3 + 2];
222 glm::vec3 u = glm::normalize(a - c);
223 glm::vec3 v = glm::normalize(b - c);
224 glm::vec3 norm = glm::normalize(glm::cross(v, u));
225 for(int j = 0; j < 3; j++) {
226 normals[i * 3 + j] = glm::vec3(norm);
230 vaos = new GLuint[2];
232 progId = compileShaders((char*)"vertex.glsl", (char*)"fragment.glsl");
233 glUseProgram(progId);
234 vaos[0] = setupBuffers(vertices, normals, progId);
235 validateProgram(progId);
237 glEnable(GL_DEPTH_TEST);
238 glEnable(GL_CULL_FACE);
241 bool* keyStates = new bool[256];
243 void keyboard(unsigned char key, int x, int y) {
244 keyStates[key] = true;
248 doRotate = !doRotate;
250 doTranslate = !doTranslate;
253 void keyboardUp(unsigned char key, int x, int y) {
254 keyStates[key] = false;
258 float xSpeed = 0.f, ySpeed = 0.f, zSpeed = 0.f;
272 camPos.x += xSpeed * sin(yaw) + zSpeed * cos(yaw);
274 camPos.z += zSpeed * sin(yaw) - xSpeed * cos(yaw);
276 glutTimerFunc(16, timer, 0);
279 int prevMouseX, prevMouseY;
280 bool firstMouse = true;
282 void motion(int x, int y) {
288 int dx = x - prevMouseX, dy = y - prevMouseY;
293 const float sensitivity = 0.005f;
294 yaw += dx * sensitivity;
295 pitch -= dy * sensitivity;
298 front.x = cos(pitch) * cos(yaw);
299 front.y = sin(pitch);
300 front.z = cos(pitch) * sin(yaw);
301 camFront = glm::normalize(front);
304 void mouse(int button, int state, int x, int y) {
305 if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
309 int main(int argc, char** argv) {
310 glutInit(&argc, argv);
311 glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGB|GLUT_3_2_CORE_PROFILE);
312 glutInitWindowSize(800, 600);
313 int win = glutCreateWindow("Hello Triangle");
314 glutDisplayFunc(display);
320 glutKeyboardFunc(keyboard);
321 glutKeyboardUpFunc(keyboardUp);
322 glutTimerFunc(16, timer, 0);
323 glutMotionFunc(motion);
324 glutMouseFunc(mouse);