Mercurial > hg > forks > gldragon
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 } |