# HG changeset patch # User Matti Hamalainen # Date 1576334360 -7200 # Node ID baccf204428914b3f3315c6393ed5a3e9c2ececd # Parent 7b138613e2fc9218a054f5243f462e5a5e2c326b Move the OpenGL rendering, setup etc. into a separate module/class, perhaps facilitating other types of renderers in future .. maybe. diff -r 7b138613e2fc -r baccf2044289 Makefile.gen --- a/Makefile.gen Sat Dec 14 14:08:51 2019 +0200 +++ b/Makefile.gen Sat Dec 14 16:39:20 2019 +0200 @@ -44,7 +44,7 @@ $(COMPILE_CXX_OBJ) -$(BINPATH)gldragon$(BINEXT): $(addprefix $(OBJPATH), gldragon.o dmscene.o dmutil.o) +$(BINPATH)gldragon$(BINEXT): $(addprefix $(OBJPATH), gldragon.o dmglrender.o dmscene.o dmutil.o) $(LINK_CXX_BIN) $(LDFLAGS) $(SDL_LDFLAGS) $(GL_LDFLAGS) $(BINPATH)ply2bin$(BINEXT): $(addprefix $(OBJPATH), ply2bin.o dmscene.o dmutil.o) diff -r 7b138613e2fc -r baccf2044289 dmglrender.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmglrender.cpp Sat Dec 14 16:39:20 2019 +0200 @@ -0,0 +1,366 @@ +// +// GLDragon - OpenGL PLY model viewer / simple benchmark +// -- OpenGL rendering of DMSimpleScene +// Programmed and designed by Matti 'ccr' Hämäläinen +// (C) Copyright 2019 Tecnic Software productions (TNSP) +// +// See file "COPYING" for license information. +// +#include "dmglrender.h" +#include + + +#ifdef GL_GLEXT_PROTOTYPES +#define DM_GLEXT_INIT(extproctype, extprocname) /* stub */ +#else +#define DM_GLEXT_INIT(extproctype, extprocname) extproctype extprocname = NULL; +#include "dmglexts.h" +#undef DM_GLEXT_INIT + + +static void dmGLCheckExtension(const std::string &name, bool &status) +{ + if (!SDL_GL_ExtensionSupported(name.c_str())) + { + status = false; + dmMsg(" - '%s' NOT supported.\n", + name.c_str()); + } +} + + +static void * dmGLGetProcAddr(const std::string &name) +{ + void *ptr = SDL_GL_GetProcAddress(name.c_str()); + + if (ptr == NULL) + dmMsg(" - '%s' NOT supported.\n"); + + return ptr; +} + + +static void * dmGLExtInit(const std::string &name, bool &status) +{ + void *ptr; + bool ok = + (ptr = dmGLGetProcAddr(name)) != NULL || + (ptr = dmGLGetProcAddr(name + "EXT")) != NULL || + (ptr = dmGLGetProcAddr(name + "ARB")) != NULL; + + if (!ok) + status = false; + + return ptr; +} +#endif + + +static bool dmCompileShader(const GLenum stype, const std::string &src, GLuint &shader) +{ + GLint status; + const char *tmp = src.c_str(); + + shader = glCreateShader(stype); + glShaderSource(shader, 1, &tmp, 0); + glCompileShader(shader); + + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if (status == GL_TRUE) + return true; + else + { + GLint bufLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &bufLen); + + if (bufLen > 0) + { + char *buf = new char[bufLen]; + glGetShaderInfoLog(shader, bufLen, NULL, buf); + dmError("Shader compilation error:\n%s\n", + buf); + delete[] buf; + } + else + { + dmError("Shader compilation error occured, but no error information got.\n"); + } + return false; + } +} + + +bool DMGLSimpleRenderer::checkErrors(void) +{ + bool ok = true; + GLenum err; + while ((err = glGetError()) != GL_NO_ERROR) + { + dmError("OpenGL error code: 0x%x (%d)\n", err); + ok = false; + } + return ok; +} + + +bool DMGLSimpleRenderer::initRender1(void) +{ + // Set GL attributes + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + //SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + return true; +} + + +bool DMGLSimpleRenderer::initRender2(SDL_Window *window) +{ + // Create OpenGL context + if ((glContext = SDL_GL_CreateContext(window)) == NULL) + { + dmError("Unable to create SDL OpenGL context: %s\n", + SDL_GetError()); + return false; + } + + // If shaders are disabled, do not initialize OpenGL extensions + if (!useShaders) + return true; + + bool status = true; + dmMsg("Checking for required OpenGL extensions ..\n"); + +#ifndef GL_GLEXT_PROTOTYPES + dmGLCheckExtension("GL_ARB_shader_objects", status); + dmGLCheckExtension("GL_ARB_shading_language_100", status); + dmGLCheckExtension("GL_ARB_vertex_shader", status); + dmGLCheckExtension("GL_ARB_fragment_shader", status); + if (!status) + { + dmError("One or more of the required OpenGL extensions not supported.\n"); + return false; + } + +#define DM_GLEXT_INIT(extproctype, extprocname) \ + extprocname = (extproctype) dmGLExtInit(#extprocname, status); +#include "dmglexts.h" +#endif + + return status; +} + + +bool DMGLSimpleRenderer::initRender3(const int width, const int height) +{ + // Dump some information + dmMsg("GL_VENDOR : %s\n", glGetString(GL_VENDOR)); + dmMsg("GL_RENDERER : %s\n", glGetString(GL_RENDERER)); + dmMsg("GL_VERSION : %s\n", glGetString(GL_VERSION)); + + if (!checkErrors()) + return false; + + // Setup the window and view port + glViewport(0, 0, width, height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45.0f, GLfloat(width) / GLfloat(height), 0.1f, 1000.0f); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // Enable back face culling + glEnable(GL_CULL_FACE); + + // Enable smooth shading + glShadeModel(GL_SMOOTH); + + // Enable the depth buffer + glEnable(GL_DEPTH_TEST); + + // Enable normal rescaling + glEnable(GL_RESCALE_NORMAL); + + glEnable(GL_COLOR_MATERIAL); + + // Setup depth buffer + glClearDepth(1.0f); + + // Set the depth buffer function + glDepthFunc(GL_LEQUAL); + + // Enable vertex and and normal arrays + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + // Set correct perspective correction + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + return checkErrors(); +} + + +bool DMGLSimpleRenderer::compileModelShaders(DMModel &model) +{ + if (useShaders) + { + if (!dmCompileShader(GL_FRAGMENT_SHADER, model.fragShaderStr, model.id_fs) || + !dmCompileShader(GL_VERTEX_SHADER, model.vertShaderStr, model.id_vs)) + return false; + + model.id_prog = glCreateProgram(); + glAttachShader(model.id_prog, model.id_fs); + glAttachShader(model.id_prog, model.id_vs); + glLinkProgram(model.id_prog); + } + return true; +} + + +void DMGLSimpleRenderer::shutdownRenderer(void) +{ + if (glContext != NULL) + SDL_GL_DeleteContext(glContext); +} + + +void DMGLSimpleRenderer::drawModel(const DMSimpleScene &scene, const DMModel &model, const float time) +{ + int maxIndices; + + if (useShaders) + { + // Enable shader program + glUseProgram(model.id_prog); + glUniform1i(glGetUniformLocation(model.id_prog, "nlights"), scene.lights.size()); + } + + // Set the material of the model + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); + glMateriali(GL_FRONT, GL_SHININESS, model.material.shininess); + glMaterialfv(GL_FRONT, GL_SPECULAR, model.material.specular.values); + glColor4fv(model.material.diffuse.values); + + // Render the model + glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxIndices); + + // Add transforms + if (model.scaleSet) + glScalef(model.scale.x, model.scale.y, model.scale.z); + + if (model.translateSet) + glTranslatef(model.translate.x, model.translate.y, model.translate.z); + + if (model.rotateSet) + { + glRotatef(model.rotate.x, 1.0f, 0.0f, 0.0f); + glRotatef(model.rotate.y, 0.0f, 1.0f, 0.0f); + glRotatef(model.rotate.z, 0.0f, 0.0f, 1.0f); + } + + glVertexPointer(3, GL_FLOAT, 0, &model.vertices[0]); + glNormalPointer( GL_FLOAT, 0, &model.normals[0]); + + for (int n = 0; n < model.nfaces; n += maxIndices) + { + const int count = std::min(maxIndices, model.nfaces - n); + glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_INT, &model.faces[n * 3]); + } + + // Restore + if (useShaders) + { + glUseProgram(0); + } +} + + +void DMGLSimpleRenderer::drawScene(const DMSimpleScene &scene, const float time) +{ + glClear(GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0.0, 1.0, 0.0, 1.0, -1, 1); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + // Draw the background gradient + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glBegin(GL_QUADS); + { + glColor3ub(0x3B, 0x3B, 0x75); + glVertex2f(0.0f, 0.0f); + glVertex2f(1.0f, 0.0f); + + glColor3ub(0x00, 0x00, 0x00); + glVertex2f(1.0f, 1.0f); + glVertex2f(0.0f, 1.0f); + } + glEnd(); + + // Restore the 3D projection + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + + // Draw models + for (const DMModel &model : scene.models) + { + glPushMatrix(); + drawModel(scene, model, time); + glPopMatrix(); + } +} + + +bool DMGLSimpleRenderer::setupLight(const int n, DMLight &light) +{ + glEnable(GL_LIGHT0 + n); + glLightfv(GL_LIGHT0 + n, GL_AMBIENT, light.color.ambient.values); + glLightfv(GL_LIGHT0 + n, GL_DIFFUSE, light.color.diffuse.values); + glLightfv(GL_LIGHT0 + n, GL_SPECULAR, light.color.specular.values); + glLightfv(GL_LIGHT0 + n, GL_POSITION, light.position.values); + return true; +} + + +bool DMGLSimpleRenderer::setupCamera(DMCamera &camera) +{ + (void) camera; + + gluLookAt(0, 0.12, 0.24, 0, 0.12, 0, 0, 1, 0); + return true; +} + + +bool DMGLSimpleRenderer::animate(DMSimpleScene &scene, const float time) +{ + (void) scene; + (void) time; + + glRotatef(2.0f, 0, 1, 0); + return true; +} diff -r 7b138613e2fc -r baccf2044289 dmglrender.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmglrender.h Sat Dec 14 16:39:20 2019 +0200 @@ -0,0 +1,40 @@ +// +// GLDragon - OpenGL PLY model viewer / simple benchmark +// -- OpenGL rendering of DMSimpleScene +// Programmed and designed by Matti 'ccr' Hämäläinen +// (C) Copyright 2019 Tecnic Software productions (TNSP) +// +// See file "COPYING" for license information. +// +#ifndef DMGLRENDER_H +#define DMGLRENDER_H 1 + +#include "dmrender.h" +#include + + +struct DMGLSimpleRenderer : DMSimpleRenderer +{ + SDL_GLContext glContext; + + DMGLSimpleRenderer() + { + glContext = NULL; + } + + bool checkErrors(void); + bool initRender1(void); + bool initRender2(SDL_Window *window); + bool initRender3(const int width, const int height); + void shutdownRenderer(void); + + void drawModel(const DMSimpleScene &scene, const DMModel &model, const float time); + void drawScene(const DMSimpleScene &scene, const float time); + + bool compileModelShaders(DMModel &model); + bool setupLight(const int n, DMLight &light); + bool setupCamera(DMCamera &camera); + bool animate(DMSimpleScene &scene, const float time); +}; + +#endif diff -r 7b138613e2fc -r baccf2044289 dmrender.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmrender.h Sat Dec 14 16:39:20 2019 +0200 @@ -0,0 +1,116 @@ +// +// GLDragon - OpenGL PLY model viewer / simple benchmark +// -- Basic renderer template +// Programmed and designed by Matti 'ccr' Hämäläinen +// (C) Copyright 2019 Tecnic Software productions (TNSP) +// +// See file "COPYING" for license information. +// +#ifndef DMRENDER_H +#define DMRENDER_H 1 + +#include "dmscene.h" +#include + + +struct DMSimpleRenderer +{ + bool useShaders; + + DMSimpleRenderer() + { + useShaders = false; + } + + virtual bool checkErrors(void) + { + return true; + } + + virtual bool initRender1(void) + { + return false; + } + + virtual bool initRender2(SDL_Window *window) + { + (void) window; + return false; + } + + virtual bool initRender3(const int width, const int height) + { + (void) width; + (void) height; + + return false; + } + + virtual void shutdownRenderer(void) + { + } + + virtual void drawModel(const DMSimpleScene &scene, const DMModel &model, const float time) + { + (void) scene; + (void) model; + (void) time; + } + + virtual void drawScene(const DMSimpleScene &scene, const float time) + { + (void) scene; + (void) time; + } + + virtual bool compileModelShaders(DMModel &model) + { + (void) model; + return false; + } + + virtual bool compileSceneShaders(DMSimpleScene &scene) + { + if (useShaders) + { + for (DMModel &model : scene.models) + { + if (!compileModelShaders(model)) + return false; + } + } + return true; + } + + virtual bool setupLight(const int n, DMLight &light) + { + (void) n; + (void) light; + return true; + } + + virtual bool setupLights(DMSimpleScene &scene) + { + for (size_t n = 0; n < scene.lights.size(); n++) + { + if (!setupLight(n, scene.lights[n])) + return false; + } + return true; + } + + virtual bool setupCamera(DMCamera &camera) + { + (void) camera; + return true; + } + + virtual bool animate(DMSimpleScene &scene, const float time) + { + (void) scene; + (void) time; + return true; + } +}; + +#endif diff -r 7b138613e2fc -r baccf2044289 gldragon.cpp --- a/gldragon.cpp Sat Dec 14 14:08:51 2019 +0200 +++ b/gldragon.cpp Sat Dec 14 16:39:20 2019 +0200 @@ -8,11 +8,8 @@ // Originally based on 'glxdragon' Copyright (c) 2009, Thomas Trummer // #include -#include -#include - #include "dmutil.h" -#include "dmscene.h" +#include "dmglrender.h" /* Default settings etc. constants @@ -34,96 +31,11 @@ /* Globals */ SDL_Window *dmWindow = NULL; -SDL_GLContext dmGLContext = NULL; /* Helpers */ -bool dmGLCheckErrors(void) -{ - bool ok = true; - GLenum err; - while ((err = glGetError()) != GL_NO_ERROR) - { - dmError("OpenGL error code: 0x%x (%d)\n", err); - ok = false; - } - return ok; -} - - -#ifdef GL_GLEXT_PROTOTYPES -#define DM_GLEXT_INIT(extproctype, extprocname) /* stub */ -#else -#define DM_GLEXT_INIT(extproctype, extprocname) extproctype extprocname = NULL; -#include "dmglexts.h" -#undef DM_GLEXT_INIT - - -void dmGLCheckExtension(const std::string &name, bool &status) -{ - if (!SDL_GL_ExtensionSupported(name.c_str())) - { - status = false; - dmMsg(" - '%s' NOT supported.\n", - name.c_str()); - } -} - - -void * dmGLGetProcAddr(const std::string &name) -{ - void *ptr = SDL_GL_GetProcAddress(name.c_str()); - - if (ptr == NULL) - dmMsg(" - '%s' NOT supported.\n"); - - return ptr; -} - - -void * dmGLExtInit(const std::string &name, bool &status) -{ - void *ptr; - bool ok = - (ptr = dmGLGetProcAddr(name)) != NULL || - (ptr = dmGLGetProcAddr(name + "EXT")) != NULL || - (ptr = dmGLGetProcAddr(name + "ARB")) != NULL; - - if (!ok) - status = false; - - return ptr; -} -#endif - - -bool dmInitGLExtensions(void) -{ - bool status = true; - dmMsg("Checking for required OpenGL extensions ..\n"); - -#ifndef GL_GLEXT_PROTOTYPES - dmGLCheckExtension("GL_ARB_shader_objects", status); - dmGLCheckExtension("GL_ARB_shading_language_100", status); - dmGLCheckExtension("GL_ARB_vertex_shader", status); - dmGLCheckExtension("GL_ARB_fragment_shader", status); - if (!status) - { - dmError("One or more of the required OpenGL extensions not supported.\n"); - return false; - } - -#define DM_GLEXT_INIT(extproctype, extprocname) \ - extprocname = (extproctype) dmGLExtInit(#extprocname, status); -#include "dmglexts.h" -#endif - - return status; -} - - -bool dmInitSDLGL(const int width, const int height, const char *title) +bool dmInitSDL(DMSimpleRenderer &renderer, const int width, const int height, const char *title) { int ret; std::string msg; @@ -136,19 +48,9 @@ return false; } - // Set GL attributes - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); - - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - //SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + // Part 1 of initialization + if (!renderer.initRender1()) + return false; // Attempt to create a window if ((dmWindow = SDL_CreateWindow(title, @@ -161,12 +63,10 @@ return false; } - if ((dmGLContext = SDL_GL_CreateContext(dmWindow)) == NULL) - { - dmError("Unable to create SDL OpenGL context: %s\n", - SDL_GetError()); + // Part 2 of initialization + if (!renderer.initRender2(dmWindow)) return false; - } + // Check if we want to attempt to use vsync switch (optVSyncMode) @@ -204,211 +104,13 @@ return false; } - // Get/initialize OpenGL extension function pointers - if (optUseShaders && !dmInitGLExtensions()) - return false; - - // Dump some information - dmMsg("GL_VENDOR : %s\n", glGetString(GL_VENDOR)); - dmMsg("GL_RENDERER : %s\n", glGetString(GL_RENDERER)); - dmMsg("GL_VERSION : %s\n", glGetString(GL_VERSION)); - dmMsg("VSync mode : %s\n", msg.c_str()); - - if (!dmGLCheckErrors()) + // Part 3 of initialization + if (!renderer.initRender3(width, height)) return false; - // Setup the window and view port - glViewport(0, 0, width, height); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - gluPerspective(45.0f, GLfloat(width) / GLfloat(height), 0.1f, 1000.0f); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - // Enable back face culling - glEnable(GL_CULL_FACE); - - // Enable smooth shading - glShadeModel(GL_SMOOTH); - - // Enable the depth buffer - glEnable(GL_DEPTH_TEST); - - // Enable normal rescaling - glEnable(GL_RESCALE_NORMAL); - - glEnable(GL_COLOR_MATERIAL); - - // Setup depth buffer - glClearDepth(1.0f); - - // Set the depth buffer function - glDepthFunc(GL_LEQUAL); - - // Enable vertex and and normal arrays - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - // Set correct perspective correction - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - - return dmGLCheckErrors(); -} - - -void dmDrawModel(const DMSimpleScene &scene, const DMModel &model) -{ - int maxIndices; - - if (optUseShaders) - { - // Enable shader program - glUseProgram(model.id_prog); - glUniform1i(glGetUniformLocation(model.id_prog, "nlights"), scene.lights.size()); - } - - // Set the material of the model - glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); - glMateriali(GL_FRONT, GL_SHININESS, model.material.shininess); - glMaterialfv(GL_FRONT, GL_SPECULAR, model.material.specular.values); - glColor4fv(model.material.diffuse.values); - - // Render the model - glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxIndices); - - // Add transforms - if (model.scaleSet) - glScalef(model.scale.x, model.scale.y, model.scale.z); - - if (model.translateSet) - glTranslatef(model.translate.x, model.translate.y, model.translate.z); - - if (model.rotateSet) - { - glRotatef(model.rotate.x, 1.0f, 0.0f, 0.0f); - glRotatef(model.rotate.y, 0.0f, 1.0f, 0.0f); - glRotatef(model.rotate.z, 0.0f, 0.0f, 1.0f); - } - - glVertexPointer(3, GL_FLOAT, 0, &model.vertices[0]); - glNormalPointer( GL_FLOAT, 0, &model.normals[0]); - - for (int n = 0; n < model.nfaces; n += maxIndices) - { - const int count = std::min(maxIndices, model.nfaces - n); - glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_INT, &model.faces[n * 3]); - } - - // Restore - if (optUseShaders) - { - glUseProgram(0); - } -} - + dmMsg("VSync mode : %s\n", msg.c_str()); -void dmDrawScene(const DMSimpleScene &scene) -{ - glClear(GL_DEPTH_BUFFER_BIT); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - glOrtho(0.0, 1.0, 0.0, 1.0, -1, 1); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - // Draw the background gradient - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glBegin(GL_QUADS); - { - glColor3ub(0x3B, 0x3B, 0x75); - glVertex2f(0.0f, 0.0f); - glVertex2f(1.0f, 0.0f); - - glColor3ub(0x00, 0x00, 0x00); - glVertex2f(1.0f, 1.0f); - glVertex2f(0.0f, 1.0f); - } - glEnd(); - - // Restore the 3D projection - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - - // Draw models - for (const DMModel &model : scene.models) - { - glPushMatrix(); - dmDrawModel(scene, model); - glPopMatrix(); - } -} - - -bool dmCompileShader(const GLenum stype, const std::string &src, GLuint &shader) -{ - GLint status; - const char *tmp = src.c_str(); - - shader = glCreateShader(stype); - glShaderSource(shader, 1, &tmp, 0); - glCompileShader(shader); - - glGetShaderiv(shader, GL_COMPILE_STATUS, &status); - if (status == GL_TRUE) - return true; - else - { - GLint bufLen = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &bufLen); - - if (bufLen > 0) - { - char *buf = new char[bufLen]; - glGetShaderInfoLog(shader, bufLen, NULL, buf); - dmError("Shader compilation error:\n%s\n", - buf); - delete[] buf; - } - else - { - dmError("Shader compilation error occured, but no error information got.\n"); - } - return false; - } -} - - -void dmLinkModelShaders(DMModel &model) -{ - model.id_prog = glCreateProgram(); - glAttachShader(model.id_prog, model.id_fs); - glAttachShader(model.id_prog, model.id_vs); - glLinkProgram(model.id_prog); -} - - -void dmSetupLight(const int n, const DMLight &light) -{ - glEnable(GL_LIGHT0 + n); - glLightfv(GL_LIGHT0 + n, GL_AMBIENT, light.color.ambient.values); - glLightfv(GL_LIGHT0 + n, GL_DIFFUSE, light.color.diffuse.values); - glLightfv(GL_LIGHT0 + n, GL_SPECULAR, light.color.specular.values); - glLightfv(GL_LIGHT0 + n, GL_POSITION, light.position.values); + return true; } @@ -421,6 +123,7 @@ optShowHelp = false, optSetInputFilename = false; std::string optInputFilename = "dragon.scene", basePath; + DMGLSimpleRenderer renderer; DMSimpleScene scene; // Check commandline argument for enabling shaders @@ -559,30 +262,20 @@ } } + // Set shader usage + renderer.useShaders = optUseShaders; + // Initialize SDL + OpenGL - if (!dmInitSDLGL(optWidth, optHeight, "GLDragon")) + if (!dmInitSDL(renderer, optWidth, optHeight, "GLDragon")) goto exit; - // According to our mode .. - if (optUseShaders) - { - for (DMModel &model : scene.models) - { - if (!dmCompileShader(GL_FRAGMENT_SHADER, model.fragShaderStr, model.id_fs) || - !dmCompileShader(GL_VERTEX_SHADER, model.vertShaderStr, model.id_vs)) - goto exit; + // Compile shaders for scene + if (!renderer.compileSceneShaders(scene)) + goto exit; - dmLinkModelShaders(model); - } - } - - // Setup lights - for (size_t n = 0; n < scene.lights.size(); n++) - dmSetupLight(n, scene.lights[n]); - - // Define the camera - gluLookAt(0, 0.12, 0.24, 0, 0.12, 0, 0, 1, 0); - + // Setup lights and camera + renderer.setupLights(scene); + renderer.setupCamera(scene.camera); // Main loop starts startTime = cycleStart = SDL_GetTicks(); @@ -610,16 +303,17 @@ } // Render the next frame - dmDrawScene(scene); + totalTime = SDL_GetTicks() - startTime; + renderer.drawScene(scene, totalTime); // Draw the current frame SDL_GL_SwapWindow(dmWindow); // Rotate for 2 degrees - glRotatef(2.0f, 0, 1, 0); + renderer.animate(scene, totalTime); // Check for errors - dmGLCheckErrors(); + renderer.checkErrors(); // Return true if a full rotation was done totalFrames++; @@ -647,8 +341,7 @@ totalTime, totalFrames, (totalFrames * 1000.0f) / totalTime); exit: - if (dmGLContext != NULL) - SDL_GL_DeleteContext(dmGLContext); + renderer.shutdownRenderer(); if (dmWindow != NULL) SDL_DestroyWindow(dmWindow);