diff gldragon.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 7b138613e2fc
children d6ffc59bb84d
line wrap: on
line diff
--- 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 <SDL.h>
-#include <SDL_opengl.h>
-#include <GL/glu.h>
-
 #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);