Fix on Mojave
[opengl.git] / assignment1.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <fstream>
4 #include <sstream>
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
13 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
14
15 using namespace std;
16
17 GLuint* vaos;
18 GLuint* progIds;
19
20 bool hasDrawn = false;
21
22 void display() {
23         glClear(GL_COLOR_BUFFER_BIT);
24         for (int i = 0; i < 2; i++) {
25                 glUseProgram(progIds[i]);
26                 glBindVertexArray(vaos[i]);
27                 glDrawArrays(GL_TRIANGLES, 0, 3);
28         }
29         glutSwapBuffers();
30         if (!hasDrawn) {
31                 glutPostRedisplay();
32                 hasDrawn = true;
33         }
34 }
35
36 void attachShader(GLuint progId, const char* filePath, GLenum type) {
37         GLuint shader = glCreateShader(type);
38
39         if (!shader) {
40                 fprintf(stderr, "error creating shader\n");
41                 exit(1);
42         }
43
44         ifstream file(filePath);
45         stringstream buffer;
46         buffer << file.rdbuf();
47         string str = buffer.str();
48         const char* contents = str.c_str();
49
50         glShaderSource(shader, 1, (const GLchar**)&contents, NULL);
51         glCompileShader(shader);
52         GLint success;
53         glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
54         if (!success) {
55                 GLchar log[1024];
56                 glGetShaderInfoLog(shader, 1024, NULL, log);
57                 fprintf(stderr, "error: %s\n", log);
58                 exit(1);
59         }
60         glAttachShader(progId, shader);
61 }
62
63 GLuint compileShaders(char* vertexShader, char* fragmentShader) {
64         GLuint progId = glCreateProgram();
65
66         attachShader(progId, vertexShader, GL_VERTEX_SHADER);
67         attachShader(progId, fragmentShader, GL_FRAGMENT_SHADER);
68
69         glLinkProgram(progId);
70         GLint success = 0;
71         glGetProgramiv(progId, GL_LINK_STATUS, &success);
72         if (!success) {
73                 GLchar log[1024];
74                 glGetProgramInfoLog(progId, sizeof(log), NULL, log);
75                 fprintf(stderr, "error linking: %s\n", log);
76                 exit(1);
77         }
78
79         return progId;
80 }
81
82 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
83
84 GLuint setupBuffers(GLfloat* vertices, GLuint progId) {
85
86         GLfloat colors[] = {
87                 0, 1, 0, 1,
88                 1, 0, 0, 1,
89                 0, 0, 1, 1
90         };
91
92         GLuint numVerts = 3;
93
94         GLuint vbo;
95         glGenBuffers(1, &vbo);
96
97         GLuint vao;
98         glGenVertexArrays(1, &vao);
99
100         GLuint posId = glGetAttribLocation(progId, "vPosition");
101         GLuint colorId = glGetAttribLocation(progId, "vColor");
102
103         GLuint vertsLen = numVerts * 3 * sizeof(GLfloat);
104         GLuint colorsLen = numVerts * 4 * sizeof(GLfloat);
105
106         glBindBuffer(GL_ARRAY_BUFFER, vbo);
107         glBufferData(GL_ARRAY_BUFFER, vertsLen + colorsLen, NULL, GL_STATIC_DRAW);
108
109         glBufferSubData(GL_ARRAY_BUFFER, 0, vertsLen, vertices);
110         glBufferSubData(GL_ARRAY_BUFFER, vertsLen, colorsLen, colors);
111         
112         glBindVertexArray(vao);
113
114         glEnableVertexAttribArray(posId);
115         glEnableVertexAttribArray(colorId);
116         
117         glVertexAttribPointer(posId, 3, GL_FLOAT, GL_FALSE, 0, 0);
118         glVertexAttribPointer(colorId, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVerts * 3 * sizeof(GLfloat)));
119
120         return vao;
121 }
122
123 void validateProgram(GLuint progId) {
124         glValidateProgram(progId);
125         
126         GLint success;
127         glGetProgramiv(progId, GL_VALIDATE_STATUS, &success);
128         if (!success) {
129                 GLchar log[1024];
130                 glGetProgramInfoLog(progId, sizeof(log), NULL, log);
131                 fprintf(stderr, "error: %s\n", log);
132                 exit(1);
133         }
134 }
135
136 void init() {
137         GLfloat vertices[2][9] = {
138                 {
139                         0.0f, -1.0f, 0.0f,
140                         1.0f, -1.0f, 0.0f,
141                         0.5f, 1.0f, 0.0f
142                 },
143
144                 {
145                         -1.0f, -1.0f, 0.0f,
146                         0.0f, -1.0f, 0.0f,
147                         -0.5f, 1.0f, 0.0f
148                 }
149         };
150
151         vaos = new GLuint[2];
152         progIds = new GLuint[2];
153
154         GLuint progId1 = compileShaders((char*)"vertex.glsl", (char*)"fragment.glsl");
155         vaos[0] = setupBuffers(vertices[0], progId1);
156         progIds[0] = progId1;
157         validateProgram(progId1);
158         
159         GLuint progId2 = compileShaders((char*)"vertex.glsl", (char*)"yellow.glsl");
160         vaos[1] = setupBuffers(vertices[1], progId2);
161         progIds[1] = progId2;
162         validateProgram(progId2);
163 }
164
165 void keyboard(unsigned char key, int x, int y) {
166         glutPostRedisplay();
167 }
168
169 int main(int argc, char** argv) {
170         glutInit(&argc, argv);
171         glutInitDisplayMode(GLUT_STENCIL|GLUT_SINGLE|GLUT_RGB|GLUT_3_2_CORE_PROFILE);
172         glutInitWindowSize(800, 600);
173         int win = glutCreateWindow("Hello Triangle");
174         glutDisplayFunc(display);
175
176         glewInit();
177         
178         init();
179
180         glutKeyboardFunc(keyboard);
181
182         glutMainLoop();
183
184         return 0;
185 }
186