renderer.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #include <SDL2/SDL.h>
  2. #include <SDL2/SDL_opengl.h>
  3. #include <assert.h>
  4. #include "renderer.h"
  5. #include "atlas.inl"
  6. #define BUFFER_SIZE 16384
  7. static GLfloat tex_buf[BUFFER_SIZE * 8];
  8. static GLfloat vert_buf[BUFFER_SIZE * 8];
  9. static GLubyte color_buf[BUFFER_SIZE * 16];
  10. static GLuint index_buf[BUFFER_SIZE * 6];
  11. static int width = 800;
  12. static int height = 600;
  13. static int buf_idx;
  14. static SDL_Window *window;
  15. void r_init(void) {
  16. /* init SDL window */
  17. window = SDL_CreateWindow(
  18. NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
  19. width, height, SDL_WINDOW_OPENGL);
  20. SDL_GL_CreateContext(window);
  21. /* init gl */
  22. glEnable(GL_BLEND);
  23. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  24. glDisable(GL_CULL_FACE);
  25. glDisable(GL_DEPTH_TEST);
  26. glEnable(GL_SCISSOR_TEST);
  27. glEnable(GL_TEXTURE_2D);
  28. glEnableClientState(GL_VERTEX_ARRAY);
  29. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  30. glEnableClientState(GL_COLOR_ARRAY);
  31. /* init texture */
  32. GLuint id;
  33. glGenTextures(1, &id);
  34. glBindTexture(GL_TEXTURE_2D, id);
  35. glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, ATLAS_WIDTH, ATLAS_HEIGHT, 0,
  36. GL_ALPHA, GL_UNSIGNED_BYTE, atlas_texture);
  37. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  38. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  39. assert(glGetError() == 0);
  40. }
  41. static void flush(void) {
  42. if (buf_idx == 0) { return; }
  43. glViewport(0, 0, width, height);
  44. glMatrixMode(GL_PROJECTION);
  45. glPushMatrix();
  46. glLoadIdentity();
  47. glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f);
  48. glMatrixMode(GL_MODELVIEW);
  49. glPushMatrix();
  50. glLoadIdentity();
  51. glTexCoordPointer(2, GL_FLOAT, 0, tex_buf);
  52. glVertexPointer(2, GL_FLOAT, 0, vert_buf);
  53. glColorPointer(4, GL_UNSIGNED_BYTE, 0, color_buf);
  54. glDrawElements(GL_TRIANGLES, buf_idx * 6, GL_UNSIGNED_INT, index_buf);
  55. glMatrixMode(GL_MODELVIEW);
  56. glPopMatrix();
  57. glMatrixMode(GL_PROJECTION);
  58. glPopMatrix();
  59. buf_idx = 0;
  60. }
  61. static void push_quad(mu_Rect dst, mu_Rect src, mu_Color color) {
  62. if (buf_idx == BUFFER_SIZE) { flush(); }
  63. int texvert_idx = buf_idx * 8;
  64. int color_idx = buf_idx * 16;
  65. int element_idx = buf_idx * 4;
  66. int index_idx = buf_idx * 6;
  67. buf_idx++;
  68. /* update texture buffer */
  69. float x = src.x / (float) ATLAS_WIDTH;
  70. float y = src.y / (float) ATLAS_HEIGHT;
  71. float w = src.w / (float) ATLAS_WIDTH;
  72. float h = src.h / (float) ATLAS_HEIGHT;
  73. tex_buf[texvert_idx + 0] = x;
  74. tex_buf[texvert_idx + 1] = y;
  75. tex_buf[texvert_idx + 2] = x + w;
  76. tex_buf[texvert_idx + 3] = y;
  77. tex_buf[texvert_idx + 4] = x;
  78. tex_buf[texvert_idx + 5] = y + h;
  79. tex_buf[texvert_idx + 6] = x + w;
  80. tex_buf[texvert_idx + 7] = y + h;
  81. /* update vertex buffer */
  82. vert_buf[texvert_idx + 0] = dst.x;
  83. vert_buf[texvert_idx + 1] = dst.y;
  84. vert_buf[texvert_idx + 2] = dst.x + dst.w;
  85. vert_buf[texvert_idx + 3] = dst.y;
  86. vert_buf[texvert_idx + 4] = dst.x;
  87. vert_buf[texvert_idx + 5] = dst.y + dst.h;
  88. vert_buf[texvert_idx + 6] = dst.x + dst.w;
  89. vert_buf[texvert_idx + 7] = dst.y + dst.h;
  90. /* update color buffer */
  91. memcpy(color_buf + color_idx + 0, &color, 4);
  92. memcpy(color_buf + color_idx + 4, &color, 4);
  93. memcpy(color_buf + color_idx + 8, &color, 4);
  94. memcpy(color_buf + color_idx + 12, &color, 4);
  95. /* update index buffer */
  96. index_buf[index_idx + 0] = element_idx + 0;
  97. index_buf[index_idx + 1] = element_idx + 1;
  98. index_buf[index_idx + 2] = element_idx + 2;
  99. index_buf[index_idx + 3] = element_idx + 2;
  100. index_buf[index_idx + 4] = element_idx + 3;
  101. index_buf[index_idx + 5] = element_idx + 1;
  102. }
  103. void r_draw_rect(mu_Rect rect, mu_Color color) {
  104. push_quad(rect, atlas[ATLAS_WHITE], color);
  105. }
  106. void r_draw_text(const char *text, mu_Vec2 pos, mu_Color color) {
  107. mu_Rect dst = { pos.x, pos.y, 0, 0 };
  108. for (const char *p = text; *p; p++) {
  109. if ((*p & 0xc0) == 0x80) { continue; }
  110. int chr = mu_min((unsigned char) *p, 127);
  111. mu_Rect src = atlas[ATLAS_FONT + chr];
  112. dst.w = src.w;
  113. dst.h = src.h;
  114. push_quad(dst, src, color);
  115. dst.x += dst.w;
  116. }
  117. }
  118. void r_draw_icon(int id, mu_Rect rect, mu_Color color) {
  119. mu_Rect src = atlas[id];
  120. int x = rect.x + (rect.w - src.w) / 2;
  121. int y = rect.y + (rect.h - src.h) / 2;
  122. push_quad(mu_rect(x, y, src.w, src.h), src, color);
  123. }
  124. int r_get_text_width(const char *text, int len) {
  125. int res = 0;
  126. for (const char *p = text; *p && len--; p++) {
  127. if ((*p & 0xc0) == 0x80) { continue; }
  128. int chr = mu_min((unsigned char) *p, 127);
  129. res += atlas[ATLAS_FONT + chr].w;
  130. }
  131. return res;
  132. }
  133. int r_get_text_height(void) {
  134. return 18;
  135. }
  136. void r_set_clip_rect(mu_Rect rect) {
  137. flush();
  138. glScissor(rect.x, height - (rect.y + rect.h), rect.w, rect.h);
  139. }
  140. void r_clear(mu_Color clr) {
  141. flush();
  142. glClearColor(clr.r / 255., clr.g / 255., clr.b / 255., clr.a / 255.);
  143. glClear(GL_COLOR_BUFFER_BIT);
  144. }
  145. void r_present(void) {
  146. flush();
  147. SDL_GL_SwapWindow(window);
  148. }