]> Dogcows Code - chaz/rasterize/blob - opengl.c
add opengl support
[chaz/rasterize] / opengl.c
1
2 /*
3 * CS5600 University of Utah
4 * Charles McGarvey
5 * mcgarvey@eng.utah.edu
6 */
7
8 #if OPENGL
9
10 #define GL_GLEXT_PROTOTYPES
11 #include <GL/gl.h>
12 #include <GL/glut.h>
13
14 #include "map.h"
15
16
17 /*
18 * More scene methods adding support for rendering with OpenGL.
19 */
20
21
22 DEFINE_MAP_TYPE2(int64_t, GLuint, model_tex);
23
24 DEFINE_ARRAY_TYPE(vec);
25 DEFINE_ARRAY_TYPE(color);
26
27
28 static scene_t* _scene = NULL;
29 static GLuint _program = 0;
30 static map_t* _textures = NULL;
31
32
33 /*
34 * Load a shader of a specified type.
35 */
36 static GLuint _gl_load_shader(const char* filename, GLenum type)
37 {
38 GLuint shader = glCreateShader(type);
39 if (shader == 0) {
40 return 0;
41 }
42
43 FILE* file = fopen(filename, "r");
44 if (file == NULL) {
45 fprintf(stderr, "Cannot read %s: %s\n", filename, strerror(errno));
46 return 0;
47 }
48
49 char* src = NULL;
50 size_t size = 0;
51 for (size_t bytes; !feof(file); size += bytes) {
52 src = mem_realloc(src, size + 4096);
53 bytes = fread(src + size, 1, 4095, file);
54 if (ferror(file)) {
55 fprintf(stderr, "Error reading %s: %s\n", filename, strerror(errno));
56 fclose(file);
57 mem_free(src);
58 return 0;
59 }
60 }
61
62 src[size] = '\0';
63 fclose(file);
64
65 glShaderSource(shader, 1, (const char**)&src, NULL);
66 glCompileShader(shader);
67
68 mem_free(src);
69
70 GLint status;
71 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
72 if (status == 0) {
73 GLint len = 0;
74 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
75 if (1 < len) {
76 char* infoLog = mem_alloc(len);
77 glGetShaderInfoLog(shader, len, NULL, infoLog);
78 fprintf(stderr, "Error compiling %s:\n%s\n", filename, infoLog);
79 mem_free(infoLog);
80 }
81 glDeleteShader(shader);
82 return 0;
83 }
84
85 return shader;
86 }
87
88
89 void _model_gl_draw(const model_t* model)
90 {
91 mat_t modelTransform;
92 model_transformation(model, &modelTransform);
93
94 GLuint model_matrix = glGetUniformLocation(_program, "model");
95 glUniformMatrix4fv(model_matrix, 1, GL_FALSE, mat_data(&modelTransform));
96
97 GLuint specular = glGetUniformLocation(_program, "mspecular");
98 color_t mspec = model_specular(model);
99 glUniform4fv(specular, 1, color_data(&mspec));
100
101 GLuint shininess = glGetUniformLocation(_program, "shininess");
102 glUniform1f(shininess, model_shininess(model));
103
104 GLuint* tex = map_model_tex_search(_textures, (int64_t)model);
105 if (tex) {
106 GLuint texture = glGetUniformLocation(_program, "sampler");
107 glUniform1i(texture, 0);
108 glActiveTexture(GL_TEXTURE0);
109 glBindTexture(GL_TEXTURE_2D, *tex);
110 GLuint is_texture = glGetUniformLocation(_program, "isTexture");
111 glUniform1i(is_texture, 1);
112 }
113 else {
114 GLuint is_texture = glGetUniformLocation(_program, "isTexture");
115 glUniform1i(is_texture, 0);
116 }
117
118 const array_t* triangles = model_geometry(model);
119 array_t* vertices = array_vec_alloc();
120 array_t* normals = array_vec_alloc();
121 array_t* texcoords = array_vec_alloc();
122 array_t* colors = array_color_alloc();
123 array_it_t it = array_begin(triangles);
124 tri_t* t;
125 while (t = array_it_tri_next(&it)) {
126 array_vec_push(vertices, t->a.v);
127 array_vec_push(vertices, t->b.v);
128 array_vec_push(vertices, t->c.v);
129 array_vec_push(normals, t->a.n);
130 array_vec_push(normals, t->b.n);
131 array_vec_push(normals, t->c.n);
132 array_vec_push(texcoords, t->a.t);
133 array_vec_push(texcoords, t->b.t);
134 array_vec_push(texcoords, t->c.t);
135 array_color_push(colors, t->a.c);
136 array_color_push(colors, t->b.c);
137 array_color_push(colors, t->c.c);
138 }
139
140 glEnableVertexAttribArray(0);
141 glEnableVertexAttribArray(1);
142 glEnableVertexAttribArray(2);
143 glEnableVertexAttribArray(3);
144
145 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vec_t), array_vec_front(vertices));
146 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(vec_t), array_vec_front(normals));
147 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(vec_t), array_vec_front(texcoords));
148 glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(vec_t), array_color_front(colors));
149
150 glDrawArrays(GL_TRIANGLES, 0, array_size(vertices));
151
152 array_destroy(vertices);
153 array_destroy(normals);
154 array_destroy(texcoords);
155 array_destroy(colors);
156
157 glBindTexture(GL_TEXTURE_2D, 0);
158 }
159
160 void _scene_glut_display()
161 {
162 assert(_scene);
163 scene_t* s = _scene;
164
165 #if VERBOSITY >= 3
166 timer_start();
167 #endif
168
169 glViewport(0, 0, s->w, s->h);
170 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
171
172 glUseProgram(_program);
173
174 GLuint view_matrix = glGetUniformLocation(_program, "view");
175 glUniformMatrix4fv(view_matrix, 1, GL_FALSE, mat_data(&s->view));
176
177 GLuint projection_matrix = glGetUniformLocation(_program, "projection");
178 glUniformMatrix4fv(projection_matrix, 1, GL_FALSE, mat_data(&s->projection));
179
180 GLuint eye_position = glGetUniformLocation(_program, "eye");
181 glUniform3fv(eye_position, 1, vec_data(&s->eye));
182
183 GLuint ambient_light = glGetUniformLocation(_program, "ambient");
184 glUniform4fv(ambient_light, 1, color_data(&s->ambient));
185
186 array_t* lightPos = array_vec_alloc();
187 array_t* lightDiffuse = array_color_alloc();
188 array_t* lightSpecular = array_color_alloc();
189
190 int count = 0;
191 for (list_t* i = s->lights; i; i = i->link) {
192 light_t* light = (light_t*)i->val;
193 ++count;
194 array_vec_push(lightPos, light->v);
195 array_color_push(lightDiffuse, light->d);
196 array_color_push(lightSpecular, light->s);
197 }
198
199 GLuint num_lights = glGetUniformLocation(_program, "numLights");
200 glUniform1i(num_lights, count);
201
202 GLuint light_position = glGetUniformLocation(_program, "light");
203 glUniform4fv(light_position, count, vec_data(array_front(lightPos)));
204
205 GLuint light_diffuse = glGetUniformLocation(_program, "diffuse");
206 glUniform4fv(light_diffuse, count, color_data(array_front(lightDiffuse)));
207
208 GLuint light_specular = glGetUniformLocation(_program, "specular");
209 glUniform4fv(light_specular, count, color_data(array_front(lightSpecular)));
210
211 array_destroy(lightPos);
212 array_destroy(lightDiffuse);
213 array_destroy(lightSpecular);
214
215 #if VERBOSITY >= 3
216 printf("rendering scene...\n");
217 #endif
218
219 for (list_t* gi = s->models; gi; gi = gi->link) {
220 model_t* m = (model_t*)gi->val;
221 _model_gl_draw(m);
222 }
223
224 #if VERBOSITY >= 3
225 long dt = timer_stop();
226 printf("render complete!\ntime\t%.3fms\n", (float)dt / 1000.0f);
227 #endif
228
229 glutSwapBuffers();
230 }
231
232 void _scene_glut_keyboard(unsigned char key, int x, int y)
233 {
234 if (key == 27) {
235 exit(0); // exit when the escape key is pressed
236 }
237 }
238
239 void _scene_gl_init()
240 {
241 assert(_scene);
242 scene_t* s = _scene;
243
244 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
245
246 glEnable(GL_DEPTH_TEST);
247 glEnable(GL_BLEND);
248 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
249 glEnable(GL_TEXTURE_2D);
250 glEnable(GL_CULL_FACE);
251
252 GLuint vShader = _gl_load_shader("vertex.glsl", GL_VERTEX_SHADER);
253 GLuint fShader = _gl_load_shader("fragment.glsl", GL_FRAGMENT_SHADER);
254 if (vShader == 0 || fShader == 0) {
255 fprintf(stderr, "One or more shaders failed to compile.");
256 exit(1);
257 }
258
259 GLuint program = glCreateProgram();
260 if (program == 0) {
261 fprintf(stderr, "Could not create GL program.");
262 exit(1);
263 }
264
265 glAttachShader(program, vShader);
266 glAttachShader(program, fShader);
267
268 glBindAttribLocation(program, 0, "vPosition");
269 glBindAttribLocation(program, 1, "vNormal");
270 glBindAttribLocation(program, 2, "vTextureCoord");
271 glBindAttribLocation(program, 3, "vColor");
272
273 glLinkProgram(program);
274
275 GLint status;
276 glGetProgramiv(program, GL_LINK_STATUS, &status);
277 if (status == 0) {
278 GLint len = 0;
279 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
280 if (1 < len) {
281 char* infoLog = mem_alloc(len);
282 glGetProgramInfoLog(program, len, NULL, infoLog);
283 fprintf(stderr, "Program link error:\n%s\n", infoLog);
284 mem_free(infoLog);
285 }
286 glDeleteProgram(program);
287 fprintf(stderr, "Could not link GL program.");
288 exit(1);
289 }
290
291 _textures = map_model_tex_alloc();
292
293 for (list_t* gi = s->models; gi; gi = gi->link) {
294 model_t* m = (model_t*)gi->val;
295 int w, h;
296 void* tdata = model_tdata(m, &w, &h);
297 if (tdata) {
298 GLuint tex;
299 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
300 glGenTextures(1, &tex);
301 glBindTexture(GL_TEXTURE_2D, tex);
302 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tdata);
303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
304 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
305 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
306 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
307 map_model_tex_insert(_textures, (int64_t)m, tex);
308 }
309 }
310 glBindTexture(GL_TEXTURE_2D, 0);
311
312 _program = program;
313 }
314
315 void _scene_glut_idle()
316 {
317 glutPostRedisplay();
318 }
319
320 void scene_render_gl(scene_t* s)
321 {
322 _scene = s;
323
324 // initialize glut
325 int argc = 0;
326 glutInit(&argc, NULL);
327 glutInitWindowSize(s->w, s->h);
328 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
329 glutCreateWindow("Project 4 Scene");
330
331 // initialize opengl
332 _scene_gl_init();
333
334 glutDisplayFunc(_scene_glut_display);
335 glutKeyboardFunc(_scene_glut_keyboard);
336 /*glutIdleFunc(_scene_glut_idle);*/
337
338 glutMainLoop();
339 }
340
341
342 #endif // OPENGL
343
This page took 0.056244 seconds and 4 git commands to generate.