Mercurial > hg > forks > gldragon
view 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 |
line wrap: on
line source
// // GLDragon - OpenGL PLY model viewer / simple benchmark // -- OpenGL rendering of DMSimpleScene // Programmed and designed by Matti 'ccr' Hämäläinen <ccr@tnsp.org> // (C) Copyright 2019 Tecnic Software productions (TNSP) // // See file "COPYING" for license information. // #include "dmglrender.h" #include <GL/glu.h> #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; }