Skip to content

Instantly share code, notes, and snippets.

@xeekworx
Last active April 11, 2024 14:34
Show Gist options
  • Save xeekworx/4c9a95c5eb67a1d3fc1fd35bacf84236 to your computer and use it in GitHub Desktop.
Save xeekworx/4c9a95c5eb67a1d3fc1fd35bacf84236 to your computer and use it in GitHub Desktop.
SDL + GLAD + OpenGL + NanoVG Example in C++
#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;
}
@despair86
Copy link

😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment