Last active
April 11, 2024 14:34
-
-
Save xeekworx/4c9a95c5eb67a1d3fc1fd35bacf84236 to your computer and use it in GitHub Desktop.
SDL + GLAD + OpenGL + NanoVG Example in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SDL.h> | |
#include <glad\glad.h> | |
#include <nanovg.h> | |
#define NANOVG_GL3_IMPLEMENTATION | |
#include <nanovg_gl.h> | |
#include <nanovg_gl_utils.h> // For framebuffer utilities not shown in this code | |
#include <string> | |
#include <iostream> | |
#include <iomanip> // for setw | |
int main(int argc, char *argv[]) | |
{ | |
int screen_width = 640, screen_height = 480; | |
SDL_Window * main_window = nullptr; | |
SDL_GLContext gl_context = nullptr; | |
NVGcontext * nvg_context = nullptr; | |
SDL_Event event = { 0 }; | |
bool should_quit = false; | |
// TRY-CATCH TO FACILITATE COMMON CLEAN-UP CODE | |
try { | |
// INITIALIZE SDL: | |
if (SDL_Init(SDL_INIT_EVENTS) < 0) { | |
throw(std::string("Failed to initialize SDL: ") + SDL_GetError()); | |
} | |
// CONFIGURE OPENGL ATTRIBUTES USING SDL: | |
int context_flags = SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG; | |
#ifdef _DEBUG | |
context_flags |= SDL_GL_CONTEXT_DEBUG_FLAG; | |
#endif | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, context_flags); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); | |
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); | |
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); | |
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); | |
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); | |
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); | |
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); | |
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); | |
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | |
// CREATE AND SDL WINDOW CONFIGURED FOR OPENGL: | |
if (0 == (main_window = SDL_CreateWindow("OpenGL Init Example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, SDL_WINDOW_OPENGL))) { | |
throw(std::string("Failed to create window: ") + SDL_GetError()); | |
} | |
// CREATE THE OPENGL CONTEXT AND MAKE IT CURRENT: | |
if(NULL == (gl_context = SDL_GL_CreateContext(main_window))) { | |
throw(std::string("Failed to create OpenGL context")); | |
} | |
else SDL_GL_MakeCurrent(main_window, gl_context); | |
// INITIALIZE GLAD: | |
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { | |
throw(std::string("Failed to initialize GLAD")); | |
} | |
// LOG OPENGL VERSION, VENDOR (IMPLEMENTATION), RENDERER, GLSL, ETC.: | |
std::cout << std::setw(34) << std::left << "OpenGL Version: " << GLVersion.major << "." << GLVersion.minor << std::endl; | |
std::cout << std::setw(34) << std::left << "OpenGL Shading Language Version: " << (char *)glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; | |
std::cout << std::setw(34) << std::left << "OpenGL Vendor:" << (char *)glGetString(GL_VENDOR) << std::endl; | |
std::cout << std::setw(34) << std::left << "OpenGL Renderer:" << (char *)glGetString(GL_RENDERER) << std::endl; | |
// INITIALIZE NANOVG: | |
int flags = NVG_STENCIL_STROKES | NVG_ANTIALIAS; | |
#ifdef _DEBUG | |
flags |= NVG_DEBUG; | |
#endif | |
if (NULL == (nvg_context = nvgCreateGL3(flags))) { | |
throw(std::string("Failed to create NVG Context")); | |
} | |
// GAME LOOP: | |
while (!should_quit) { | |
// EVENT LOOP: | |
while (SDL_PollEvent(&event)) { | |
switch (event.type) { | |
case SDL_QUIT: | |
should_quit = true; | |
break; | |
case SDL_KEYDOWN: | |
switch (event.key.keysym.sym) { | |
case SDLK_ESCAPE: | |
should_quit = true; | |
break; | |
} | |
break; | |
} | |
} | |
// RENDERING GOES HERE: | |
// ... | |
// Clear the screen to WHITE: | |
glClearColor(1.f, 1.f, 1.f, 1.f); | |
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | |
// BEGIN NANOVG DRAWING: | |
nvgBeginFrame(nvg_context, screen_width, screen_height, 1.f); | |
// DRAW A ROUND RECTANGLE WITH AN OUTLINE: | |
float rect_w = 250.f, rect_h = 250.f; | |
NVGcolor nvg_stroke_color = nvgRGBAf(0.f, 0.f, 0.f, 1.f); | |
NVGcolor nvg_fill_color = nvgRGBAf(0.f, 1.f, 0.1f, 1.f); | |
nvgBeginPath(nvg_context); | |
nvgRoundedRectVarying( | |
nvg_context, | |
(float)screen_width / 2.f - rect_w / 2.f, screen_height / 2.f - rect_h / 2.f, | |
rect_w, rect_h, | |
30.f, 8.f, 30.f, 8.f | |
); | |
nvgFillColor(nvg_context, nvg_fill_color); | |
nvgFill(nvg_context); | |
nvgStrokeWidth(nvg_context, 2.f); | |
nvgStrokeColor(nvg_context, nvg_stroke_color); | |
nvgStroke(nvg_context); | |
// END NANOVG DRAWING: | |
nvgEndFrame(nvg_context); | |
// PRESENT BACKBUFFER: | |
SDL_GL_SwapWindow(main_window); | |
} | |
} | |
catch (std::string e) { | |
std::cout << e << std::endl;; | |
} | |
catch (...) { | |
std::cout << "Unknown exception caught!" << std::endl; | |
} | |
if (nvg_context) nvgDeleteGL3(nvg_context); | |
if (gl_context) SDL_GL_DeleteContext(gl_context); | |
if (main_window) SDL_DestroyWindow(main_window); | |
SDL_Quit(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
😄