comparison dmglrender.cpp @ 62:baccf2044289

Move the OpenGL rendering, setup etc. into a separate module/class, perhaps facilitating other types of renderers in future .. maybe.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 14 Dec 2019 16:39:20 +0200
parents
children d6ffc59bb84d
comparison
equal deleted inserted replaced
61:7b138613e2fc 62:baccf2044289
1 //
2 // GLDragon - OpenGL PLY model viewer / simple benchmark
3 // -- OpenGL rendering of DMSimpleScene
4 // Programmed and designed by Matti 'ccr' Hämäläinen <ccr@tnsp.org>
5 // (C) Copyright 2019 Tecnic Software productions (TNSP)
6 //
7 // See file "COPYING" for license information.
8 //
9 #include "dmglrender.h"
10 #include <GL/glu.h>
11
12
13 #ifdef GL_GLEXT_PROTOTYPES
14 #define DM_GLEXT_INIT(extproctype, extprocname) /* stub */
15 #else
16 #define DM_GLEXT_INIT(extproctype, extprocname) extproctype extprocname = NULL;
17 #include "dmglexts.h"
18 #undef DM_GLEXT_INIT
19
20
21 static void dmGLCheckExtension(const std::string &name, bool &status)
22 {
23 if (!SDL_GL_ExtensionSupported(name.c_str()))
24 {
25 status = false;
26 dmMsg(" - '%s' NOT supported.\n",
27 name.c_str());
28 }
29 }
30
31
32 static void * dmGLGetProcAddr(const std::string &name)
33 {
34 void *ptr = SDL_GL_GetProcAddress(name.c_str());
35
36 if (ptr == NULL)
37 dmMsg(" - '%s' NOT supported.\n");
38
39 return ptr;
40 }
41
42
43 static void * dmGLExtInit(const std::string &name, bool &status)
44 {
45 void *ptr;
46 bool ok =
47 (ptr = dmGLGetProcAddr(name)) != NULL ||
48 (ptr = dmGLGetProcAddr(name + "EXT")) != NULL ||
49 (ptr = dmGLGetProcAddr(name + "ARB")) != NULL;
50
51 if (!ok)
52 status = false;
53
54 return ptr;
55 }
56 #endif
57
58
59 static bool dmCompileShader(const GLenum stype, const std::string &src, GLuint &shader)
60 {
61 GLint status;
62 const char *tmp = src.c_str();
63
64 shader = glCreateShader(stype);
65 glShaderSource(shader, 1, &tmp, 0);
66 glCompileShader(shader);
67
68 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
69 if (status == GL_TRUE)
70 return true;
71 else
72 {
73 GLint bufLen = 0;
74 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &bufLen);
75
76 if (bufLen > 0)
77 {
78 char *buf = new char[bufLen];
79 glGetShaderInfoLog(shader, bufLen, NULL, buf);
80 dmError("Shader compilation error:\n%s\n",
81 buf);
82 delete[] buf;
83 }
84 else
85 {
86 dmError("Shader compilation error occured, but no error information got.\n");
87 }
88 return false;
89 }
90 }
91
92
93 bool DMGLSimpleRenderer::checkErrors(void)
94 {
95 bool ok = true;
96 GLenum err;
97 while ((err = glGetError()) != GL_NO_ERROR)
98 {
99 dmError("OpenGL error code: 0x%x (%d)\n", err);
100 ok = false;
101 }
102 return ok;
103 }
104
105
106 bool DMGLSimpleRenderer::initRender1(void)
107 {
108 // Set GL attributes
109 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
110 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
111 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
112
113 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
114 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
115 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
116 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
117
118 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
119 //SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
120 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
121
122 return true;
123 }
124
125
126 bool DMGLSimpleRenderer::initRender2(SDL_Window *window)
127 {
128 // Create OpenGL context
129 if ((glContext = SDL_GL_CreateContext(window)) == NULL)
130 {
131 dmError("Unable to create SDL OpenGL context: %s\n",
132 SDL_GetError());
133 return false;
134 }
135
136 // If shaders are disabled, do not initialize OpenGL extensions
137 if (!useShaders)
138 return true;
139
140 bool status = true;
141 dmMsg("Checking for required OpenGL extensions ..\n");
142
143 #ifndef GL_GLEXT_PROTOTYPES
144 dmGLCheckExtension("GL_ARB_shader_objects", status);
145 dmGLCheckExtension("GL_ARB_shading_language_100", status);
146 dmGLCheckExtension("GL_ARB_vertex_shader", status);
147 dmGLCheckExtension("GL_ARB_fragment_shader", status);
148 if (!status)
149 {
150 dmError("One or more of the required OpenGL extensions not supported.\n");
151 return false;
152 }
153
154 #define DM_GLEXT_INIT(extproctype, extprocname) \
155 extprocname = (extproctype) dmGLExtInit(#extprocname, status);
156 #include "dmglexts.h"
157 #endif
158
159 return status;
160 }
161
162
163 bool DMGLSimpleRenderer::initRender3(const int width, const int height)
164 {
165 // Dump some information
166 dmMsg("GL_VENDOR : %s\n", glGetString(GL_VENDOR));
167 dmMsg("GL_RENDERER : %s\n", glGetString(GL_RENDERER));
168 dmMsg("GL_VERSION : %s\n", glGetString(GL_VERSION));
169
170 if (!checkErrors())
171 return false;
172
173 // Setup the window and view port
174 glViewport(0, 0, width, height);
175
176 glMatrixMode(GL_PROJECTION);
177 glLoadIdentity();
178
179 gluPerspective(45.0f, GLfloat(width) / GLfloat(height), 0.1f, 1000.0f);
180
181 glMatrixMode(GL_MODELVIEW);
182 glLoadIdentity();
183
184 // Enable back face culling
185 glEnable(GL_CULL_FACE);
186
187 // Enable smooth shading
188 glShadeModel(GL_SMOOTH);
189
190 // Enable the depth buffer
191 glEnable(GL_DEPTH_TEST);
192
193 // Enable normal rescaling
194 glEnable(GL_RESCALE_NORMAL);
195
196 glEnable(GL_COLOR_MATERIAL);
197
198 // Setup depth buffer
199 glClearDepth(1.0f);
200
201 // Set the depth buffer function
202 glDepthFunc(GL_LEQUAL);
203
204 // Enable vertex and and normal arrays
205 glEnableClientState(GL_VERTEX_ARRAY);
206 glEnableClientState(GL_NORMAL_ARRAY);
207
208 // Set correct perspective correction
209 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
210
211 return checkErrors();
212 }
213
214
215 bool DMGLSimpleRenderer::compileModelShaders(DMModel &model)
216 {
217 if (useShaders)
218 {
219 if (!dmCompileShader(GL_FRAGMENT_SHADER, model.fragShaderStr, model.id_fs) ||
220 !dmCompileShader(GL_VERTEX_SHADER, model.vertShaderStr, model.id_vs))
221 return false;
222
223 model.id_prog = glCreateProgram();
224 glAttachShader(model.id_prog, model.id_fs);
225 glAttachShader(model.id_prog, model.id_vs);
226 glLinkProgram(model.id_prog);
227 }
228 return true;
229 }
230
231
232 void DMGLSimpleRenderer::shutdownRenderer(void)
233 {
234 if (glContext != NULL)
235 SDL_GL_DeleteContext(glContext);
236 }
237
238
239 void DMGLSimpleRenderer::drawModel(const DMSimpleScene &scene, const DMModel &model, const float time)
240 {
241 int maxIndices;
242
243 if (useShaders)
244 {
245 // Enable shader program
246 glUseProgram(model.id_prog);
247 glUniform1i(glGetUniformLocation(model.id_prog, "nlights"), scene.lights.size());
248 }
249
250 // Set the material of the model
251 glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
252 glMateriali(GL_FRONT, GL_SHININESS, model.material.shininess);
253 glMaterialfv(GL_FRONT, GL_SPECULAR, model.material.specular.values);
254 glColor4fv(model.material.diffuse.values);
255
256 // Render the model
257 glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxIndices);
258
259 // Add transforms
260 if (model.scaleSet)
261 glScalef(model.scale.x, model.scale.y, model.scale.z);
262
263 if (model.translateSet)
264 glTranslatef(model.translate.x, model.translate.y, model.translate.z);
265
266 if (model.rotateSet)
267 {
268 glRotatef(model.rotate.x, 1.0f, 0.0f, 0.0f);
269 glRotatef(model.rotate.y, 0.0f, 1.0f, 0.0f);
270 glRotatef(model.rotate.z, 0.0f, 0.0f, 1.0f);
271 }
272
273 glVertexPointer(3, GL_FLOAT, 0, &model.vertices[0]);
274 glNormalPointer( GL_FLOAT, 0, &model.normals[0]);
275
276 for (int n = 0; n < model.nfaces; n += maxIndices)
277 {
278 const int count = std::min(maxIndices, model.nfaces - n);
279 glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_INT, &model.faces[n * 3]);
280 }
281
282 // Restore
283 if (useShaders)
284 {
285 glUseProgram(0);
286 }
287 }
288
289
290 void DMGLSimpleRenderer::drawScene(const DMSimpleScene &scene, const float time)
291 {
292 glClear(GL_DEPTH_BUFFER_BIT);
293
294 glMatrixMode(GL_PROJECTION);
295 glPushMatrix();
296 glLoadIdentity();
297
298 glOrtho(0.0, 1.0, 0.0, 1.0, -1, 1);
299
300 glMatrixMode(GL_MODELVIEW);
301 glPushMatrix();
302 glLoadIdentity();
303
304 // Draw the background gradient
305 glDisable(GL_DEPTH_TEST);
306 glDisable(GL_LIGHTING);
307 glBegin(GL_QUADS);
308 {
309 glColor3ub(0x3B, 0x3B, 0x75);
310 glVertex2f(0.0f, 0.0f);
311 glVertex2f(1.0f, 0.0f);
312
313 glColor3ub(0x00, 0x00, 0x00);
314 glVertex2f(1.0f, 1.0f);
315 glVertex2f(0.0f, 1.0f);
316 }
317 glEnd();
318
319 // Restore the 3D projection
320 glMatrixMode(GL_PROJECTION);
321 glPopMatrix();
322
323 glMatrixMode(GL_MODELVIEW);
324 glPopMatrix();
325
326 glEnable(GL_DEPTH_TEST);
327 glEnable(GL_LIGHTING);
328
329 // Draw models
330 for (const DMModel &model : scene.models)
331 {
332 glPushMatrix();
333 drawModel(scene, model, time);
334 glPopMatrix();
335 }
336 }
337
338
339 bool DMGLSimpleRenderer::setupLight(const int n, DMLight &light)
340 {
341 glEnable(GL_LIGHT0 + n);
342 glLightfv(GL_LIGHT0 + n, GL_AMBIENT, light.color.ambient.values);
343 glLightfv(GL_LIGHT0 + n, GL_DIFFUSE, light.color.diffuse.values);
344 glLightfv(GL_LIGHT0 + n, GL_SPECULAR, light.color.specular.values);
345 glLightfv(GL_LIGHT0 + n, GL_POSITION, light.position.values);
346 return true;
347 }
348
349
350 bool DMGLSimpleRenderer::setupCamera(DMCamera &camera)
351 {
352 (void) camera;
353
354 gluLookAt(0, 0.12, 0.24, 0, 0.12, 0, 0, 1, 0);
355 return true;
356 }
357
358
359 bool DMGLSimpleRenderer::animate(DMSimpleScene &scene, const float time)
360 {
361 (void) scene;
362 (void) time;
363
364 glRotatef(2.0f, 0, 1, 0);
365 return true;
366 }