Skip to content

Instantly share code, notes, and snippets.

@xeekworx
Last active July 28, 2018 19:27
Show Gist options
  • Save xeekworx/f2c0141aa474aba8eda6fea5072bf379 to your computer and use it in GitHub Desktop.
Save xeekworx/f2c0141aa474aba8eda6fea5072bf379 to your computer and use it in GitHub Desktop.
SDL + GLAD + OpenGL + NanoVG Example in C++ (Triangle)
#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
void nvgTriangle(NVGcontext * ctx, float x1, float y1, float x2, float y2, float x3, float y3);
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);
float triW = 350.f, triH = 300.f;
float triX = screen_width / 2 - triW / 2;
float triY = screen_height / 2 - triH / 2;
nvgTriangle(nvg_context, triX + triW / 2, triY + 0, triX + triW, triY + triH, triX + 0, triY + triH);
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;
}
void nvgTriangle(NVGcontext * ctx, float x1, float y1, float x2, float y2, float x3, float y3)
{
nvgMoveTo(ctx, x1, y1);
nvgLineTo(ctx, x2, y2);
nvgLineTo(ctx, x3, y3);
nvgClosePath(ctx);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment