Golias Engine
A C++ 20 'game engine' built with SDL3 with wide platform support.
nuklear_sdl3_gl3.h
Go to the documentation of this file.
1 /*
2  * Nuklear - 1.32.0 - public domain
3  * --------------------------------------------------------------
4  * Public domain — no warranty; use at your own risk.
5  *
6  * Author: Vinicius Gabriel (2025)
7  * GitHub: https://github.com/vsaint1
8  *
9  * Usage:
10  *
11  #define NK_INCLUDE_FIXED_TYPES
12  #define NK_INCLUDE_STANDARD_IO
13  #define NK_INCLUDE_STANDARD_VARARGS
14  #define NK_INCLUDE_DEFAULT_ALLOCATOR
15  #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
16  #define NK_INCLUDE_FONT_BAKING
17  #define NK_INCLUDE_DEFAULT_FONT
18  #define NK_SDL3_GL3_IMPLEMENTATION
19  #define NK_IMPLEMENTATION
20  #include "nuklear_sdl3_gl3.h"
21 
22 
23  #define MAX_VERTEX_MEMORY 512 * 1024
24  #define MAX_ELEMENT_MEMORY 128 * 1024
25  *
26  *
27  * Notes:
28  * - Nuklear minimal version 1.32.0
29  * - SDL3 minimal version 3.0.0
30  *
31  *
32  * ===============================================================
33  */
34 #ifndef NK_SDL_GL3_H_
35 #define NK_SDL_GL3_H_
36 
37 #include <nuklear.h>
38 #include <SDL3/SDL.h>
39 #include <SDL3/SDL_opengl.h>
40 
41 NK_API struct nk_context* nk_sdl_init(SDL_Window *win);
42 NK_API void nk_sdl_font_stash_begin(struct nk_font_atlas **atlas);
43 NK_API void nk_sdl_font_stash_end(void);
44 NK_API int nk_sdl_handle_event(SDL_Event *evt);
45 NK_API void nk_sdl_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer);
46 NK_API void nk_sdl_shutdown(void);
47 NK_API void nk_sdl_device_destroy(void);
48 NK_API void nk_sdl_device_create(void);
49 NK_API void nk_sdl_handle_grab(void);
50 
51 #endif
52 
53 #define GL_CALL_RET(x) ({ \
54  auto __ret = (x); \
55  GLenum __err = glGetError(); \
56  if(__err != GL_NO_ERROR) \
57  fprintf(stderr, "GL error 0x%X at %s:%d in %s\n", __err, __FILE__, __LINE__, __func__); \
58  __ret; \
59 })
60 
61 #define GL_CALL(x) do { \
62  x; \
63  GLenum err = glGetError(); \
64  if (err != GL_NO_ERROR) { \
65  fprintf(stderr, "[GL ERROR] %s:%d %s -> 0x%X\n", __FILE__, __LINE__, #x, err); \
66  } \
67 } while(0)
68 
69 /*
70  * ==============================================================
71  *
72  * IMPLEMENTATION
73  *
74  * ===============================================================
75  */
76 #ifdef NK_SDL3_GL3_IMPLEMENTATION
77 
78 #include <stdlib.h>
79 #include <assert.h>
80 #include <string.h>
81 
82 struct nk_sdl_device {
83  struct nk_buffer cmds;
84  struct nk_draw_null_texture tex_null;
85  GLuint vbo, vao, ebo;
86  GLuint prog;
87  GLuint vert_shdr;
88  GLuint frag_shdr;
89  GLint attrib_pos;
90  GLint attrib_uv;
91  GLint attrib_col;
92  GLint uniform_tex;
93  GLint uniform_proj;
94  GLuint font_tex;
95 };
96 
97 struct nk_sdl_vertex {
98  float position[2];
99  float uv[2];
100  nk_byte col[4];
101 };
102 
103 static struct nk_sdl {
104  SDL_Window *win;
105  struct nk_sdl_device ogl;
106  struct nk_context ctx;
107  struct nk_font_atlas atlas;
108  Uint64 time_of_last_frame;
109 } sdl;
110 
111 #if defined(SDL_PLATFORM_ANDROID) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_EMSCRIPTEN)
112 #define SHADER_HEADER "#version 300 es\nprecision mediump float;\n"
113 #else
114 #define SHADER_HEADER "#version 330 core\n"
115 #endif
116 
117 
118 NK_API void
120 {
121  GLint status;
122  static const GLchar *vertex_shader =
124  "uniform mat4 ProjMtx;\n"
125  "in vec2 Position;\n"
126  "in vec2 TexCoord;\n"
127  "in vec4 Color;\n"
128  "out vec2 Frag_UV;\n"
129  "out vec4 Frag_Color;\n"
130  "void main() {\n"
131  " Frag_UV = TexCoord;\n"
132  " Frag_Color = Color;\n"
133  " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n"
134  "}\n";
135  static const GLchar *fragment_shader =
137  "uniform sampler2D Texture;\n"
138  "in vec2 Frag_UV;\n"
139  "in vec4 Frag_Color;\n"
140  "out vec4 Out_Color;\n"
141  "void main(){\n"
142  " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
143  "}\n";
144 
145  struct nk_sdl_device *dev = &sdl.ogl;
146  nk_buffer_init_default(&dev->cmds);
147  dev->prog = glCreateProgram();
148  dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER);
149  dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER);
150  glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0);
151  glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0);
152  glCompileShader(dev->vert_shdr);
153  glCompileShader(dev->frag_shdr);
154  glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status);
155  assert(status == GL_TRUE);
156  glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status);
157  assert(status == GL_TRUE);
158  glAttachShader(dev->prog, dev->vert_shdr);
159  glAttachShader(dev->prog, dev->frag_shdr);
160  glLinkProgram(dev->prog);
161  glGetProgramiv(dev->prog, GL_LINK_STATUS, &status);
162  assert(status == GL_TRUE);
163 
164  dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture");
165  dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx");
166  dev->attrib_pos = glGetAttribLocation(dev->prog, "Position");
167  dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord");
168  dev->attrib_col = glGetAttribLocation(dev->prog, "Color");
169 
170  {
171  /* buffer setup */
172  GLsizei vs = sizeof(struct nk_sdl_vertex);
173  size_t vp = offsetof(struct nk_sdl_vertex, position);
174  size_t vt = offsetof(struct nk_sdl_vertex, uv);
175  size_t vc = offsetof(struct nk_sdl_vertex, col);
176 
177  glGenBuffers(1, &dev->vbo);
178  glGenBuffers(1, &dev->ebo);
179  glGenVertexArrays(1, &dev->vao);
180 
181  glBindVertexArray(dev->vao);
182  glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
183  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
184 
185  glEnableVertexAttribArray((GLuint)dev->attrib_pos);
186  glEnableVertexAttribArray((GLuint)dev->attrib_uv);
187  glEnableVertexAttribArray((GLuint)dev->attrib_col);
188 
189  glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
190  glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
191  glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);
192  }
193 
194  glBindTexture(GL_TEXTURE_2D, 0);
195  glBindBuffer(GL_ARRAY_BUFFER, 0);
196  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
197  glBindVertexArray(0);
198 }
199 
200 NK_INTERN void
201 nk_sdl_device_upload_atlas(const void *image, int width, int height)
202 {
203  struct nk_sdl_device *dev = &sdl.ogl;
204  glGenTextures(1, &dev->font_tex);
205  glBindTexture(GL_TEXTURE_2D, dev->font_tex);
206  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
207  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
208  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
209  GL_RGBA, GL_UNSIGNED_BYTE, image);
210 }
211 
212 NK_API void
214 {
215  struct nk_sdl_device *dev = &sdl.ogl;
216  glDetachShader(dev->prog, dev->vert_shdr);
217  glDetachShader(dev->prog, dev->frag_shdr);
218  glDeleteShader(dev->vert_shdr);
219  glDeleteShader(dev->frag_shdr);
220  glDeleteProgram(dev->prog);
221  glDeleteTextures(1, &dev->font_tex);
222  glDeleteBuffers(1, &dev->vbo);
223  glDeleteBuffers(1, &dev->ebo);
224  nk_buffer_free(&dev->cmds);
225 }
226 
227 NK_API void
228 nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer)
229 {
230  struct nk_sdl_device *dev = &sdl.ogl;
231  int width, height;
232  int display_width, display_height;
233  struct nk_vec2 scale;
234  GLfloat ortho[4][4] = {
235  { 2.0f, 0.0f, 0.0f, 0.0f },
236  { 0.0f, -2.0f, 0.0f, 0.0f },
237  { 0.0f, 0.0f, -1.0f, 0.0f },
238  { -1.0f, 1.0f, 0.0f, 1.0f },
239  };
240 
241  Uint64 now = SDL_GetTicks();
242  sdl.ctx.delta_time_seconds = (float)(now - sdl.time_of_last_frame) / 1000;
243  sdl.time_of_last_frame = now;
244 
245  SDL_GetWindowSize(sdl.win, &width, &height);
246  SDL_GetWindowSizeInPixels(sdl.win, &display_width, &display_height);
247  ortho[0][0] /= (GLfloat)width;
248  ortho[1][1] /= (GLfloat)height;
249 
250  scale.x = (float)display_width / (float)width;
251  scale.y = (float)display_height / (float)height;
252 
253  glViewport(0, 0, display_width, display_height);
254  glEnable(GL_BLEND);
255  glBlendEquation(GL_FUNC_ADD);
256  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
257  glDisable(GL_CULL_FACE);
258  glDisable(GL_DEPTH_TEST);
259  glEnable(GL_SCISSOR_TEST);
260  glActiveTexture(GL_TEXTURE0);
261 
262  glUseProgram(dev->prog);
263  glUniform1i(dev->uniform_tex, 0);
264  glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]);
265 
266  {
267  const struct nk_draw_command *cmd;
268  void *vertices, *elements;
269  const nk_draw_index *offset = NULL;
270  struct nk_buffer vbuf, ebuf;
271 
272  glBindVertexArray(dev->vao);
273  glBindBuffer(GL_ARRAY_BUFFER, dev->vbo);
274  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo);
275 
276  glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW);
277  glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW);
278 
279  vertices = malloc(max_vertex_buffer);
280  elements = malloc(max_element_buffer);
281 
282  {
283  struct nk_convert_config config;
284  static const struct nk_draw_vertex_layout_element vertex_layout[] = {
285  {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sdl_vertex, position)},
286  {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sdl_vertex, uv)},
287  {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_sdl_vertex, col)},
288  {NK_VERTEX_LAYOUT_END}
289  };
290  memset(&config, 0, sizeof(config));
291  config.vertex_layout = vertex_layout;
292  config.vertex_size = sizeof(struct nk_sdl_vertex);
293  config.vertex_alignment = NK_ALIGNOF(struct nk_sdl_vertex);
294  config.tex_null = dev->tex_null;
295  config.circle_segment_count = 22;
296  config.curve_segment_count = 22;
297  config.arc_segment_count = 22;
298  config.global_alpha = 1.0f;
299  config.shape_AA = AA;
300  config.line_AA = AA;
301 
302  nk_buffer_init_fixed(&vbuf, vertices, (nk_size)max_vertex_buffer);
303  nk_buffer_init_fixed(&ebuf, elements, (nk_size)max_element_buffer);
304  nk_convert(&sdl.ctx, &dev->cmds, &vbuf, &ebuf, &config);
305  }
306 
307  /*
308  NOTE: glMapBuffer doesnt work on OpenGL ES 2/3, i did this to keep cross-platform
309  */
310  glBufferSubData(GL_ARRAY_BUFFER, 0, max_vertex_buffer, vertices);
311  glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, max_element_buffer, elements);
312 
313  free(vertices);
314  free(elements);
315 
316  /* iterate over and execute each draw command */
317  nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds) {
318  if (!cmd->elem_count) continue;
319  glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
320  glScissor(
321  (GLint)(cmd->clip_rect.x * scale.x),
322  (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y),
323  (GLint)(cmd->clip_rect.w * scale.x),
324  (GLint)(cmd->clip_rect.h * scale.y)
325  );
326  glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
327  offset += cmd->elem_count;
328  }
329 
330  nk_clear(&sdl.ctx);
331  nk_buffer_clear(&dev->cmds);
332  }
333 
334  glUseProgram(0);
335  glBindBuffer(GL_ARRAY_BUFFER, 0);
336  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
337  glBindVertexArray(0);
338  glDisable(GL_BLEND);
339  glDisable(GL_SCISSOR_TEST);
340 }
341 
342 static void
343 nk_sdl_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
344 {
345  const char *text = SDL_GetClipboardText();
346  if (text) {
347  nk_textedit_paste(edit, text, nk_strlen(text));
348  SDL_free((void *)text);
349  }
350  (void)usr;
351 }
352 
353 static void
354 nk_sdl_clipboard_copy(nk_handle usr, const char *text, int len)
355 {
356  char *str = 0;
357  (void)usr;
358  if (!len) return;
359  str = (char*)malloc((size_t)len+1);
360  if (!str) return;
361  memcpy(str, text, (size_t)len);
362  str[len] = '\0';
363  SDL_SetClipboardText(str);
364  free(str);
365 }
366 
367 NK_API struct nk_context*
368 nk_sdl_init(SDL_Window *win)
369 {
370  sdl.win = win;
371  nk_init_default(&sdl.ctx, 0);
372  sdl.ctx.clip.copy = nk_sdl_clipboard_copy;
373  sdl.ctx.clip.paste = nk_sdl_clipboard_paste;
374  sdl.ctx.clip.userdata = nk_handle_ptr(0);
376  sdl.time_of_last_frame = SDL_GetTicks();
377  return &sdl.ctx;
378 }
379 
380 NK_API void
381 nk_sdl_font_stash_begin(struct nk_font_atlas **atlas)
382 {
383  nk_font_atlas_init_default(&sdl.atlas);
384  nk_font_atlas_begin(&sdl.atlas);
385  *atlas = &sdl.atlas;
386 }
387 
388 NK_API void
390 {
391  const void *image; int w, h;
392  image = nk_font_atlas_bake(&sdl.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
393  nk_sdl_device_upload_atlas(image, w, h);
394  nk_font_atlas_end(&sdl.atlas, nk_handle_id((int)sdl.ogl.font_tex), &sdl.ogl.tex_null);
395  if (sdl.atlas.default_font)
396  nk_style_set_font(&sdl.ctx, &sdl.atlas.default_font->handle);
397 
398 }
399 
400 NK_API void
401 nk_sdl_handle_grab(void)
402 {
403  struct nk_context *ctx = &sdl.ctx;
404  if (ctx->input.mouse.grab) {
405  SDL_SetWindowRelativeMouseMode(sdl.win, true);
406  } else if (ctx->input.mouse.ungrab) {
407  /* better support for older SDL by setting mode first; causes an extra mouse motion event */
408  SDL_SetWindowRelativeMouseMode(sdl.win, false);
409  SDL_WarpMouseInWindow(sdl.win, (int)ctx->input.mouse.prev.x, (int)ctx->input.mouse.prev.y);
410  } else if (ctx->input.mouse.grabbed) {
411  ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
412  ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
413  }
414 }
415 
416 NK_API int
417 nk_sdl_handle_event(SDL_Event *evt)
418 {
419  struct nk_context *ctx = &sdl.ctx;
420  int ctrl_down = SDL_GetModState() & (SDL_KMOD_LCTRL | SDL_KMOD_RCTRL);
421 
422  switch(evt->type)
423  {
424  case SDL_EVENT_KEY_UP: /* KEYUP & KEYDOWN share same routine */
425  case SDL_EVENT_KEY_DOWN:
426  {
427  int down = evt->type == SDL_EVENT_KEY_DOWN;
428  switch(evt->key.key)
429  {
430  case SDLK_RSHIFT: /* RSHIFT & LSHIFT share same routine */
431  case SDLK_LSHIFT: nk_input_key(ctx, NK_KEY_SHIFT, down); break;
432  case SDLK_DELETE: nk_input_key(ctx, NK_KEY_DEL, down); break;
433 
434  case SDLK_KP_ENTER:
435  case SDLK_RETURN: nk_input_key(ctx, NK_KEY_ENTER, down); break;
436 
437  case SDLK_TAB: nk_input_key(ctx, NK_KEY_TAB, down); break;
438  case SDLK_BACKSPACE: nk_input_key(ctx, NK_KEY_BACKSPACE, down); break;
439  case SDLK_HOME: nk_input_key(ctx, NK_KEY_TEXT_START, down);
440  nk_input_key(ctx, NK_KEY_SCROLL_START, down); break;
441  case SDLK_END: nk_input_key(ctx, NK_KEY_TEXT_END, down);
442  nk_input_key(ctx, NK_KEY_SCROLL_END, down); break;
443  case SDLK_PAGEDOWN: nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); break;
444  case SDLK_PAGEUP: nk_input_key(ctx, NK_KEY_SCROLL_UP, down); break;
445  case SDLK_Z: nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && ctrl_down); break;
446  case SDLK_R: nk_input_key(ctx, NK_KEY_TEXT_REDO, down && ctrl_down); break;
447  case SDLK_C: nk_input_key(ctx, NK_KEY_COPY, down && ctrl_down); break;
448  case SDLK_V: nk_input_key(ctx, NK_KEY_PASTE, down && ctrl_down); break;
449  case SDLK_X: nk_input_key(ctx, NK_KEY_CUT, down && ctrl_down); break;
450  case SDLK_B: nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && ctrl_down); break;
451  case SDLK_E: nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && ctrl_down); break;
452  case SDLK_UP: nk_input_key(ctx, NK_KEY_UP, down); break;
453  case SDLK_DOWN: nk_input_key(ctx, NK_KEY_DOWN, down); break;
454  case SDLK_A:
455  if (ctrl_down)
456  nk_input_key(ctx,NK_KEY_TEXT_SELECT_ALL, down);
457  break;
458  case SDLK_LEFT:
459  if (ctrl_down)
460  nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
461  else nk_input_key(ctx, NK_KEY_LEFT, down);
462  break;
463  case SDLK_RIGHT:
464  if (ctrl_down)
465  nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
466  else nk_input_key(ctx, NK_KEY_RIGHT, down);
467  break;
468  }
469  }
470  return 1;
471 
472  case SDL_EVENT_MOUSE_BUTTON_UP: /* MOUSEBUTTONUP & MOUSEBUTTONDOWN share same routine */
473  case SDL_EVENT_MOUSE_BUTTON_DOWN:
474  {
475  int down = evt->type == SDL_EVENT_MOUSE_BUTTON_DOWN;
476  const int x = evt->button.x, y = evt->button.y;
477  switch(evt->button.button)
478  {
479  case SDL_BUTTON_LEFT:
480  if (evt->button.clicks > 1)
481  nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, down);
482  nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); break;
483  case SDL_BUTTON_MIDDLE: nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); break;
484  case SDL_BUTTON_RIGHT: nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); break;
485  }
486  }
487  return 1;
488 
489  case SDL_EVENT_MOUSE_MOTION:
490  if (ctx->input.mouse.grabbed) {
491  int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
492  nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel);
493  }
494  else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
495  return 1;
496 
497  case SDL_EVENT_TEXT_INPUT:
498  {
499 
500  nk_rune unicode;
501  int glyph_len;
502  int byte_len;
503  const char *text = evt->text.text;
504  glyph_len = byte_len = nk_utf_decode(text, &unicode, 4);
505  while (unicode != '\0' && glyph_len) {
506  nk_input_unicode(ctx, unicode);
507  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
508  byte_len += glyph_len;
509  }
510  }
511  return 1;
512 
513  case SDL_EVENT_MOUSE_WHEEL:
514  nk_input_scroll(ctx,nk_vec2(evt->wheel.x, evt->wheel.y));
515  return 1;
516  }
517  return 0;
518 }
519 
520 NK_API
521 void nk_sdl_shutdown(void)
522 {
523  nk_font_atlas_clear(&sdl.atlas);
524  nk_free(&sdl.ctx);
526  memset(&sdl, 0, sizeof(sdl));
527 }
528 
529 #endif
NK_API int nk_sdl_handle_event(SDL_Event *evt)
NK_API void nk_sdl_render(enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer)
NK_API void nk_sdl_font_stash_begin(struct nk_font_atlas **atlas)
NK_API void nk_sdl_handle_grab(void)
NK_API void nk_sdl_device_create(void)
NK_API struct nk_context * nk_sdl_init(SDL_Window *win)
NK_API void nk_sdl_shutdown(void)
NK_API void nk_sdl_device_destroy(void)
NK_API void nk_sdl_font_stash_end(void)
#define SHADER_HEADER
Definition: ogl_struct.cpp:7