this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #128 from RandomErrorMessage/nanovg

adding NanoVG example

authored by

Jonathan Dearborn and committed by
GitHub
0a308f63 0a468edf

+138
+138
demos/nanovg/main.c
··· 1 + #include <SDL2/SDL.h> 2 + #include <SDL2/SDL_gpu.h> 3 + 4 + #define GLEW_STATIC // needed for windows only(?) 5 + #include <GL/glew.h> 6 + 7 + #define NANOVG_GL3_IMPLEMENTATION 8 + #include "nanovg/nanovg.h" 9 + #include "nanovg/nanovg_gl.h" 10 + #include "nanovg/nanovg_gl_utils.h" 11 + 12 + /* Create a GPU_Image from a NanoVG Framebuffer */ 13 + GPU_Image* generateFBO(NVGcontext* _vg, const float _w, const float _h, void (*draw)(NVGcontext*, const float, const float, const float, const float)) { 14 + // GPU_FlushBlitBuffer(); // call GPU_FlushBlitBuffer if you're doing this in the middle of SDL_gpu blitting 15 + NVGLUframebuffer* fb = nvgluCreateFramebuffer(_vg, _w, _h, NVG_IMAGE_NODELETE); // IMPORTANT: NVG_IMAGE_NODELETE allows us to run nvgluDeleteFramebuffer without freeing the GPU_Image data 16 + nvgluBindFramebuffer(fb); 17 + glViewport(0, 0, _w, _h); 18 + glClearColor(0, 0, 0, 0); 19 + glClear(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 20 + nvgBeginFrame(_vg, _w, _h, 1.0f); 21 + draw(_vg, 0, 0, _w, _h); // call the drawing function that was passed as parameter 22 + nvgEndFrame(_vg); 23 + /* nvgluBindFramebuffer(0); // official documentation says to unbind, but I haven't had issues not doing it */ 24 + GPU_ResetRendererState(); // not calling GPU_ResetRendererState can cause problems with SDL_gpu depending on your order of operations 25 + // IMPORTANT: don't run nvgluDeleteFramebuffer, GPU_CreateImageUsingTexture takes the handle 26 + GPU_Image* return_image = GPU_CreateImageUsingTexture(fb->texture, false); // should take_ownership be true? 27 + nvgluDeleteFramebuffer(fb); 28 + return return_image; 29 + } 30 + 31 + /* Simple Drawing Example */ 32 + void drawNVG(NVGcontext* _vg, const float _x, const float _y, const float _w, const float _h) { 33 + const float square_r = 5.0f; 34 + nvgBeginPath(_vg); 35 + nvgRoundedRect(_vg, _x, _y, _w, _h, square_r); 36 + NVGpaint bg_paint = nvgLinearGradient(_vg, _x, _y, _x+_w, _y+_h, nvgRGBA(255, 255, 255, 255), nvgRGBA(255, 255, 255, 155)); 37 + nvgFillPaint(_vg, bg_paint); 38 + nvgFill(_vg); 39 + } 40 + 41 + /* draw something that takes some awhile */ 42 + void drawComplexNVG(NVGcontext* _vg, const float _x, const float _y, const float _w, const float _h) { 43 + float x = _x; 44 + float y = _y; 45 + nvgBeginPath(_vg); 46 + nvgMoveTo(_vg, x, y); 47 + for (unsigned i = 1; i < 50000; i++) { 48 + nvgBezierTo(_vg, x-10.0f, y+10.0f, x+25, y+25, x,y); 49 + x += 10.0f; 50 + y += 5.0f; 51 + if (x > _w) 52 + x = 0.0f; 53 + if (y > _h) 54 + y = 0.0f; 55 + } 56 + NVGpaint stroke_paint = nvgLinearGradient(_vg, _x, _y, _w, _h, nvgRGBA(255, 255, 255, 20), nvgRGBA(0, 255, 255, 10)); 57 + nvgStrokePaint(_vg, stroke_paint); 58 + nvgStroke(_vg); 59 + } 60 + 61 + /* Can help show STENCIL problems when _arc_radius because concave (convex?) */ 62 + void drawPie(NVGcontext* _vg, const float _x, const float _y, const float _arc_radius) { 63 + const float pie_radius = 100.0f; 64 + nvgBeginPath(_vg); 65 + nvgMoveTo(_vg, _x, _y); 66 + nvgArc(_vg, _x, _y, pie_radius, 0.0f, nvgDegToRad(_arc_radius), NVG_CW); 67 + nvgLineTo(_vg, _x, _y); 68 + nvgFillColor(_vg, nvgRGBA(0xFF,0xFF,0xFF,0xFF)); 69 + nvgFill(_vg); 70 + } 71 + 72 + void main_loop(GPU_Target* _screen, NVGcontext* _vg, const Uint16 _screen_w, const Uint16 _screen_h) { 73 + const float px_ratio = (float)_screen_w / (float)_screen_w; // spoilers: it's 1.0f 74 + 75 + GPU_Rect fbo_simple_rect = { 65.0f, 10.0f, 50.0f, 50.0f}; // Blitting Destination 76 + GPU_Image* fbo_simple = generateFBO(_vg, fbo_simple_rect.w, fbo_simple_rect.h, drawNVG); 77 + 78 + GPU_Rect fbo_complex_rect = { 0.0f, 0.0f, _screen_w, _screen_h}; // Blitting Destination 79 + GPU_Image* fbo_complex = generateFBO(_vg, fbo_complex_rect.w, fbo_complex_rect.h, drawComplexNVG); 80 + 81 + float arc_radius = 0.0f; 82 + 83 + SDL_Event event; 84 + bool loop = true; 85 + do { 86 + /* SDL Event Handling */ 87 + while(SDL_PollEvent(&event)) { 88 + if(event.type == SDL_QUIT) 89 + loop = false; 90 + else if(event.type == SDL_KEYDOWN) { 91 + if(event.key.keysym.sym == SDLK_ESCAPE) 92 + loop = false; 93 + } 94 + } 95 + 96 + /* Animation Pass */ 97 + arc_radius += 1.0f; 98 + 99 + /* SDL_gpu + NanoVG Rendering */ 100 + GPU_ClearRGBA(_screen, 0x00, 0x00, 0x00, 0xFF); // GPU_ClearRGBA clears GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT 101 + glClear(GL_STENCIL_BUFFER_BIT); // IMPORTANT: GPU_ClearRGBA does not clear GL_STENCIL_BUFFER_BIT 102 + 103 + /* SDL_gpu Blitting */ 104 + GPU_BlitRectX(fbo_complex, NULL, _screen, &fbo_complex_rect, 0.0f, 0.0f, 0.0f, GPU_FLIP_VERTICAL); // IMPORTANT: GPU_BlitRectX is required to use GPU_FLIP_VERTICAL which is required for NVGLUframebuffer data (why???) 105 + GPU_BlitRectX(fbo_simple, NULL, _screen, &fbo_simple_rect, 0.0f, 0.0f, 0.0f, GPU_FLIP_VERTICAL); // IMPORTANT: GPU_BlitRectX is required to use GPU_FLIP_VERTICAL which is required for NVGLUframebuffer data (why???) 106 + 107 + /* NanoVG Section */ 108 + GPU_FlushBlitBuffer(); // IMPORTANT: run GPU_FlushBlitBuffer before nvgBeginFrame 109 + nvgBeginFrame(_vg, _screen_w, _screen_h, px_ratio); // Do your normal NanoVG stuff 110 + drawNVG(_vg, 10.0f, 10.0f, fbo_simple_rect.w, fbo_simple_rect.h); // run our simple drawing code directly 111 + drawPie(_vg, _screen_w/2, _screen_h/2, arc_radius); // drawing the pie chart will break if you don't have a stencil buffer 112 + /* drawComplexNVG(_vg); */ 113 + nvgEndFrame(_vg); // Finish our NanoVG pass 114 + GPU_ResetRendererState(); // IMPORTANT: run GPU_ResetRendererState after nvgEndFrame 115 + 116 + /* Finish */ 117 + GPU_Flip(_screen); // Render to screen 118 + } while (loop); 119 + 120 + /* Loops over, Cleanup */ 121 + GPU_FreeImage(fbo_simple); 122 + GPU_FreeImage(fbo_complex); 123 + } 124 + 125 + int main() { 126 + const Uint16 screen_w = 500; 127 + const Uint16 screen_h = 500; 128 + 129 + /* Init SDL and our renderer, no error handling! */ 130 + SDL_Init(SDL_INIT_EVERYTHING); // Init SDL 131 + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); // NanoVG _REQUIRES_ a stencil buffer 132 + GPU_Target* target = GPU_InitRenderer(GPU_RENDERER_OPENGL_3, screen_w, screen_h, 0); // Init SDL_gpu 133 + NVGcontext* vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG); // Init NanoVG 134 + 135 + main_loop(target, vg, screen_w, screen_h); 136 + 137 + return 0; 138 + }