Last active
July 28, 2018 19:27
-
-
Save xeekworx/f2c0141aa474aba8eda6fea5072bf379 to your computer and use it in GitHub Desktop.
SDL + GLAD + OpenGL + NanoVG Example in C++ (Triangle)
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 | |
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