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