CSCI441 OpenGL Library 5.9.0
CS@Mines CSCI441 Computer Graphics Course Library
Loading...
Searching...
No Matches
OpenGLEngine.hpp
Go to the documentation of this file.
1
12#ifndef CSCI441_OPENGL_ENGINE_HPP
13#define CSCI441_OPENGL_ENGINE_HPP
14
15#include "OpenGLUtils.hpp"
16
17#ifdef CSCI441_USE_GLEW
18 #include <GL/glew.h>
19#else
20 #include <glad/gl.h>
21#endif
22
23#include <GLFW/glfw3.h>
24
25#include <cstdio>
26#include <cstring>
27#include <set>
28#include <string>
29
30namespace CSCI441 {
31
40 public:
44 OpenGLEngine(const OpenGLEngine&) = delete;
49
57 virtual void initialize();
61 virtual void run() = 0;
69 virtual void shutdown();
70
75 [[maybe_unused]] virtual void turnDebuggingOn() noexcept final { DEBUG = true; }
80 virtual void turnDebuggingOff() noexcept final { DEBUG = false; }
84 [[maybe_unused]] [[nodiscard]] virtual bool isDebuggingEnabled() const noexcept final { return DEBUG; }
85
91 [[maybe_unused]] [[nodiscard]] virtual bool isExtensionEnabled(const std::string EXT) const noexcept final { return _extensions.find(EXT) != _extensions.end(); }
92
101 virtual void setCurrentWindowSize(const int WINDOW_WIDTH, const int WINDOW_HEIGHT) final { mWindowWidth = WINDOW_WIDTH; mWindowHeight = WINDOW_HEIGHT; }
105 [[maybe_unused]] [[nodiscard]] virtual int getWindowHeight() const noexcept final { return mWindowHeight; }
109 [[maybe_unused]] [[nodiscard]] virtual int getWindowWidth() const noexcept final { return mWindowWidth; }
113 [[maybe_unused]] [[nodiscard]] virtual GLFWwindow* getWindow() const noexcept final { return mpWindow; }
114
118 [[maybe_unused]] virtual void setWindowShouldClose() final { glfwSetWindowShouldClose(mpWindow, GLFW_TRUE); }
119
123 [[nodiscard]] virtual unsigned short getError() noexcept final {
124 unsigned short storedErrorCode = mErrorCode; // store current error code
125 mErrorCode = OPENGL_ENGINE_ERROR_NO_ERROR; // reset error code
126 return storedErrorCode; // return previously stored error code
127 }
128
132 static const unsigned short OPENGL_ENGINE_ERROR_NO_ERROR = 0;
136 static const unsigned short OPENGL_ENGINE_ERROR_GLFW_INIT = 1;
140 static const unsigned short OPENGL_ENGINE_ERROR_GLFW_WINDOW = 2;
144 static const unsigned short OPENGL_ENGINE_ERROR_GLEW_INIT = 3;
148 static const unsigned short OPENGL_ENGINE_ERROR_GLAD_INIT = 4;
152 static const unsigned short OPENGL_ENGINE_ERROR_UNKNOWN = 5;
153 // note to developers: if more error codes are added, need to update LAST accordingly or
154 // update UNKNOWN to the last value and shift
163 [[maybe_unused]] static const unsigned short OPENGL_ENGINE_ERROR_SIZE = OPENGL_ENGINE_ERROR_LAST + 1;
164
165 protected:
177 OpenGLEngine(int OPENGL_MAJOR_VERSION, int OPENGL_MINOR_VERSION, int WINDOW_WIDTH, int WINDOW_HEIGHT, const char* WINDOW_TITLE, bool WINDOW_RESIZABLE = GLFW_FALSE);
182 virtual ~OpenGLEngine();
183
188 bool DEBUG;
189
193 unsigned int mErrorCode;
194
227 GLFWwindow *mpWindow;
228
235 static void mErrorCallback(int error, const char* DESCRIPTION) { fprintf(stderr, "[ERROR]: %d\n\t%s\n", error, DESCRIPTION ); }
236
240 static void mDebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
241 fprintf( stdout, "[VERBOSE]: Debug Message (%d): source = %s, type = %s, severity = %s, message = %s\n",
242 id,
243 CSCI441::OpenGLUtils::debugSourceToString(source),
244 CSCI441::OpenGLUtils::debugTypeToString(type),
245 CSCI441::OpenGLUtils::debugSeverityToString(severity),
246 message
247 );
248 }
249
257 static void mWindowResizeCallback(GLFWwindow* pWindow, int width, int height);
258
278 virtual void mSetupGLFW();
285 virtual void mSetupOpenGL() = 0;
292 virtual void mSetupShaders() {};
298 virtual void mSetupBuffers() {};
304 virtual void mSetupTextures() {}
310 virtual void mSetupScene() {};
311
316 virtual void mCleanupScene() {};
321 virtual void mCleanupTextures() {}
326 virtual void mCleanupBuffers() {};
331 virtual void mCleanupShaders() {};
336 virtual void mCleanupOpenGL() {};
343 virtual void mCleanupGLFW();
344
345 private:
346 void _setupGLFunctions(); // initialize OpenGL functions
347 void _cleanupGLFunctions() {} // nothing to be done at this time
348
349 bool _isInitialized; // makes initialization a singleton process
350 bool _isCleanedUp; // makes cleanup a singleton process
351
352 std::set< std::string > _extensions;// set of all available OpenGL extensions
353 };
354}
355
356inline CSCI441::OpenGLEngine::OpenGLEngine(const int OPENGL_MAJOR_VERSION, const int OPENGL_MINOR_VERSION, const int WINDOW_WIDTH, const int WINDOW_HEIGHT, const char* WINDOW_TITLE, const bool WINDOW_RESIZABLE)
357 : mOpenGLMajorVersion(OPENGL_MAJOR_VERSION), mOpenGLMinorVersion(OPENGL_MINOR_VERSION), mWindowWidth(WINDOW_WIDTH), mWindowHeight(WINDOW_HEIGHT), mWindowResizable(WINDOW_RESIZABLE) {
358
359 mWindowTitle = (char*)malloc(sizeof(char) * strlen(WINDOW_TITLE));
360 strcpy(mWindowTitle, WINDOW_TITLE);
361
362 mpWindow = nullptr;
363
364 _isInitialized = _isCleanedUp = false;
365 DEBUG = true;
367}
368
370 shutdown();
371 free(mWindowTitle);
372}
373
375 if( !_isInitialized ) {
376 mSetupGLFW(); // initialize GLFW and set up a window
377 _setupGLFunctions(); // create OpenGL function pointers
378 mSetupOpenGL(); // create the OpenGL context
379
380 // get OpenGL context information
381 if( DEBUG ) {
382 // if wanting debug information with Version 4.3 or higher
383 if( mOpenGLMajorVersion > 4 || (mOpenGLMajorVersion == 4 && mOpenGLMinorVersion >= 3) ) {
384 // check if debug context was created
385 int flags; glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
386 if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) {
387 // register callback to synchronously print any debug messages without having to call glGetError()
388 glEnable(GL_DEBUG_OUTPUT);
389 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
390 glDebugMessageCallback(mDebugMessageCallback, nullptr);
391 glDebugMessageControl( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE );
392 }
393 }
394
395 CSCI441::OpenGLUtils::printOpenGLInfo();
396 }
397
398 mSetupShaders(); // transfer, compile, link shaders on GPU
399 mSetupBuffers(); // register Buffers on GPU
400 mSetupTextures(); // register Textures on GPU
401 mSetupScene(); // setup any scene specific information
402
403 _isInitialized = true;
404 _isCleanedUp = false;
405 if (DEBUG) fprintf(stdout, "\n[INFO]: Setup complete\n");
406 }
407}
408
410 // set what function to use when registering errors
411 // this is the ONLY GLFW function that can be called BEFORE GLFW is initialized
412 // all other GLFW calls must be performed after GLFW has been initialized
413 glfwSetErrorCallback(mErrorCallback);
414
415 // initialize GLFW
416 if( !glfwInit() ) {
417 fprintf( stderr, "[ERROR]: Could not initialize GLFW\n" );
418 mErrorCode = OPENGL_ENGINE_ERROR_GLFW_INIT;
419 } else {
420 if(DEBUG) fprintf( stdout, "[INFO]: GLFW %d.%d.%d initialized\n", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION );
421
422 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, mOpenGLMajorVersion ); // request OpenGL vX.
423 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, mOpenGLMinorVersion ); // request OpenGL v .X
424 glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE ); // request forward compatible OpenGL context
425 glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE ); // request OpenGL Core Profile context
426 glfwWindowHint( GLFW_DOUBLEBUFFER, GLFW_TRUE ); // request double buffering
427 glfwWindowHint(GLFW_RESIZABLE, mWindowResizable ); // set if our window should be able to be resized
428
429 // if wanting debug information with Version 4.3 or higher
430 if( DEBUG
431 && (mOpenGLMajorVersion > 4 || (mOpenGLMajorVersion == 4 && mOpenGLMinorVersion >= 3)) ) {
432 glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); // request a debug context
433 }
434
435 // create a window for a given size, with a given title
436 mpWindow = glfwCreateWindow(mWindowWidth, mWindowHeight, mWindowTitle, nullptr, nullptr );
437 if( !mpWindow ) { // if the window could not be created, NULL is returned
438 fprintf( stderr, "[ERROR]: GLFW Window could not be created\n" );
439 glfwTerminate();
440 mErrorCode = OPENGL_ENGINE_ERROR_GLFW_WINDOW;
441 } else {
442 if(DEBUG) fprintf( stdout, "[INFO]: GLFW Window created\n" );
443 glfwMakeContextCurrent(mpWindow); // make the created window the current window
444 glfwSwapInterval(1); // update our screen after at least 1 screen refresh
445 glfwSetInputMode(mpWindow, GLFW_LOCK_KEY_MODS, GLFW_TRUE); // track state of Caps Lock and Num Lock keys
446 glfwSetWindowUserPointer(mpWindow, (void*)this);
447 glfwSetWindowSizeCallback(mpWindow, mWindowResizeCallback);
448 }
449 }
450}
451
452inline void CSCI441::OpenGLEngine::_setupGLFunctions() {
453
454#ifdef CSCI441_USE_GLEW
455 glewExperimental = GL_TRUE;
456 GLenum glewResult = glewInit(); // initialize GLEW
457
458 // check for an error
459 if( glewResult != GLEW_OK ) {
460 fprintf( stderr, "[ERROR]: Error initializing GLEW\n");
461 fprintf( stderr, "[ERROR]: %s\n", glewGetErrorString(glewResult) );
462 mErrorCode = OPENGL_ENGINE_ERROR_GLEW_INIT;
463 } else {
464 if(DEBUG) {
465 fprintf(stdout, "\n[INFO]: GLEW initialized\n");
466 fprintf(stdout, "[INFO]: Using GLEW %s\n", glewGetString(GLEW_VERSION));
467 }
468 }
469#else
470 int version = gladLoadGL(glfwGetProcAddress);
471 if(version == 0) {
472 fprintf(stderr, "Failed to initialize GLAD\n" );
473 mErrorCode = OPENGL_ENGINE_ERROR_GLAD_INIT;
474 } else {
475 if(DEBUG) {
476 // Successfully loaded OpenGL
477 fprintf(stdout, "\n[INFO]: GLAD initialized\n");
478 fprintf(stdout, "[INFO]: Loaded OpenGL %d.%d\n", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version));
479 }
480 }
481#endif
482
483 if(mErrorCode == OPENGL_ENGINE_ERROR_NO_ERROR) {
484 GLint numExtensions = 0;
485 glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
486 for (int i = 0; i < numExtensions; i++) {
487 _extensions.insert((const char*)glGetStringi(GL_EXTENSIONS, i) );
488 }
489 }
490}
491
493 if(DEBUG) fprintf( stdout, "[INFO]: ...closing window...\n" );
494 glfwDestroyWindow(mpWindow ); // close our window
495 mpWindow = nullptr;
496 if(DEBUG) fprintf( stdout, "[INFO]: ...closing GLFW.....\n" );
497 glfwTerminate();
498}
499
501 if( !_isCleanedUp ) {
502 if (DEBUG) fprintf(stdout, "\n[INFO]: Shutting down.......\n");
503 mCleanupShaders(); // delete shaders from GPU
504 mCleanupBuffers(); // delete VAOs/VBOs from GPU
505 mCleanupTextures(); // delete textures from GPU
506 mCleanupScene(); // delete scene info from CPU
507 mCleanupOpenGL(); // cleanup anything OpenGL related
508 _cleanupGLFunctions(); // cleanup anything function pointer related
509 mCleanupGLFW(); // shut down GLFW to clean up our context
510 if (DEBUG) fprintf(stdout, "[INFO]: ..shut down complete!\n");
511 _isCleanedUp = true;
512 _isInitialized = false;
513 }
514}
515
516inline void CSCI441::OpenGLEngine::mWindowResizeCallback(GLFWwindow* pWindow, int width, int height) {
517 auto pEngine = (OpenGLEngine*) glfwGetWindowUserPointer(pWindow);
518 pEngine->setCurrentWindowSize(width, height);
519}
520
521#endif //CSCI441_OPENGL_ENGINE_HPP
Helper functions to work with OpenGL 3.0+.
Abstract Class to run an OpenGL application. The following methods must be overridden:
Definition: OpenGLEngine.hpp:39
virtual void mSetupOpenGL()=0
override to enable specific OpenGL features
virtual bool isExtensionEnabled(const std::string EXT) const noexcept final
Returns if OpenGL extension exists.
Definition: OpenGLEngine.hpp:91
static const unsigned short OPENGL_ENGINE_ERROR_NO_ERROR
no error is present, everything is currently working
Definition: OpenGLEngine.hpp:132
bool DEBUG
if information should be printed to console while running
Definition: OpenGLEngine.hpp:188
OpenGLEngine & operator=(const OpenGLEngine &)=delete
do not allow engines to be copied
int mOpenGLMinorVersion
the minor version of the requested OpenGL context
Definition: OpenGLEngine.hpp:204
int mOpenGLMajorVersion
the major version of the requested OpenGL context
Definition: OpenGLEngine.hpp:199
virtual void setCurrentWindowSize(const int WINDOW_WIDTH, const int WINDOW_HEIGHT) final
Set the new window size.
Definition: OpenGLEngine.hpp:101
virtual void initialize()
Initialize everything needed for OpenGL Rendering. This includes in order: GLFW, function pointers,...
Definition: OpenGLEngine.hpp:374
virtual void shutdown()
Cleanup everything needed for OpenGL Rendering. This includes freeing memory for data used in: any Sc...
Definition: OpenGLEngine.hpp:500
virtual unsigned short getError() noexcept final
Return current value of error code and clear the error code back to no error.
Definition: OpenGLEngine.hpp:123
virtual void mSetupTextures()
override to register any textures with the GPU
Definition: OpenGLEngine.hpp:304
virtual int getWindowHeight() const noexcept final
Return the height of the window.
Definition: OpenGLEngine.hpp:105
virtual bool isDebuggingEnabled() const noexcept final
Returns if logging is enabled.
Definition: OpenGLEngine.hpp:84
static void mWindowResizeCallback(GLFWwindow *pWindow, int width, int height)
Definition: OpenGLEngine.hpp:516
virtual void mCleanupBuffers()
override to cleanup any buffer objects from the GPU
Definition: OpenGLEngine.hpp:326
virtual void mCleanupScene()
override to cleanup any scene specific information
Definition: OpenGLEngine.hpp:316
virtual void mCleanupShaders()
override to cleanup any shaders from the GPU
Definition: OpenGLEngine.hpp:331
static const unsigned short OPENGL_ENGINE_ERROR_UNKNOWN
a new error that does not correspond to a predefined scenario has occurred
Definition: OpenGLEngine.hpp:152
static const unsigned short OPENGL_ENGINE_ERROR_LAST
stores the error code number of the last possible error, this corresponds to the max error code value...
Definition: OpenGLEngine.hpp:159
static const unsigned short OPENGL_ENGINE_ERROR_GLAD_INIT
an error occurred while initializing GLAD
Definition: OpenGLEngine.hpp:148
virtual void mCleanupTextures()
override to cleanup any textures from the GPU
Definition: OpenGLEngine.hpp:321
bool mWindowResizable
if the GLFW window can be resized while open
Definition: OpenGLEngine.hpp:219
OpenGLEngine(const OpenGLEngine &)=delete
do not allow engines to be copied
virtual void turnDebuggingOn() noexcept final
Enable logging to command line.
Definition: OpenGLEngine.hpp:75
static const unsigned short OPENGL_ENGINE_ERROR_GLFW_INIT
an error occurred while initializing GLFW
Definition: OpenGLEngine.hpp:136
unsigned int mErrorCode
tracks the current status of the OpenGL engine via error codes
Definition: OpenGLEngine.hpp:193
virtual void run()=0
Initiate the draw loop.
char * mWindowTitle
the title of the GLFW window
Definition: OpenGLEngine.hpp:223
static void mDebugMessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)
callback called whenever a debug message is signaled
Definition: OpenGLEngine.hpp:240
static const unsigned short OPENGL_ENGINE_ERROR_GLFW_WINDOW
an error occurred while creating the GLFW window
Definition: OpenGLEngine.hpp:140
int mWindowHeight
the window height of the requested GLFW window
Definition: OpenGLEngine.hpp:214
virtual void setWindowShouldClose() final
Tell our engine's window to close.
Definition: OpenGLEngine.hpp:118
static const unsigned short OPENGL_ENGINE_ERROR_SIZE
stores the number of unique error codes that can be generated
Definition: OpenGLEngine.hpp:163
virtual void mSetupShaders()
override to register any shaders with the GPU
Definition: OpenGLEngine.hpp:292
GLFWwindow * mpWindow
pointer to the GLFW window object
Definition: OpenGLEngine.hpp:227
virtual void turnDebuggingOff() noexcept final
Disable logging to command line.
Definition: OpenGLEngine.hpp:80
virtual int getWindowWidth() const noexcept final
Return the width of the window.
Definition: OpenGLEngine.hpp:109
virtual void mSetupBuffers()
override to register any buffer objects with the GPU
Definition: OpenGLEngine.hpp:298
virtual ~OpenGLEngine()
cleans up our OpenGL Engine by destroying the OpenGL context, GLFW window, and cleaning up all GPU re...
Definition: OpenGLEngine.hpp:369
static const unsigned short OPENGL_ENGINE_ERROR_GLEW_INIT
an error occurred while initializing GLEW
Definition: OpenGLEngine.hpp:144
virtual void mCleanupGLFW()
Destroys the associated GLFW window and terminates the GLFW instance.
Definition: OpenGLEngine.hpp:492
int mWindowWidth
the window width of the requested GLFW window
Definition: OpenGLEngine.hpp:209
virtual void mCleanupOpenGL()
override to cleanup any specific OpenGL features
Definition: OpenGLEngine.hpp:336
virtual void mSetupGLFW()
Used to setup everything GLFW related. This includes the OpenGL context and our window....
Definition: OpenGLEngine.hpp:409
static void mErrorCallback(int error, const char *DESCRIPTION)
We will register this function as GLFW's error callback. When an error within OpenGL occurs,...
Definition: OpenGLEngine.hpp:235
virtual void mSetupScene()
override to setup any scene specific information
Definition: OpenGLEngine.hpp:310
virtual GLFWwindow * getWindow() const noexcept final
Return the window object.
Definition: OpenGLEngine.hpp:113
CSCI441 Helper Functions for OpenGL.
Definition: ArcballCam.hpp:17