delete unused include
[full-beans.git] / demo / renderer.c
blob4fccb1269bfa07c2f76fa6b61f05e003550b0164
1 #include "fenster.h"
2 #include <assert.h>
3 #include <stdbool.h>
4 #include "renderer.h"
5 #include "atlas.inl"
7 #define BUFFER_SIZE 16384
9 typedef uint8_t byte;
11 static mu_Rect tex_buf[BUFFER_SIZE];
12 static mu_Rect src_buf[BUFFER_SIZE];
13 static mu_Color color_buf[BUFFER_SIZE];
15 static int buf_idx;
17 static struct fenster window = {.title="A window", .width=800, .height=600};
19 static mu_Rect clip_rect;
21 void r_init(void) {
22 /* init SDL window */
23 window.buf = malloc(window.width * window.height * sizeof(*window.buf));
24 r_clear(mu_color(0, 0, 0, 255));
25 fenster_open(&window);
27 /* init texture */
30 static inline bool within(int c, int lo, int hi) {
31 return c >= lo && c < hi;
34 static inline bool within_rect(mu_Rect rect, int x, int y) {
35 return within(x, rect.x, rect.x+rect.w)
36 && within(y, rect.y, rect.y+rect.h);
39 static inline bool same_size(const mu_Rect* a, const mu_Rect* b) {
40 return a->w == b->w && a->h == b->h;
43 static inline byte texture_color(const mu_Rect* tex, int x, int y) {
44 assert(x < tex->w);
45 x = x + tex->x;
46 assert(y < tex->h);
47 y = y + tex->y;
48 return atlas_texture[y*ATLAS_WIDTH + x];
51 static inline uint32_t r_color(mu_Color clr) {
52 return ((uint32_t)clr.a << 24) | ((uint32_t)clr.r << 16) | ((uint32_t)clr.g << 8) | clr.b;
55 mu_Color mu_color_argb(uint32_t clr) {
56 return mu_color((clr >> 16) & 0xff, (clr >> 8) & 0xff, clr & 0xff, (clr >> 24) & 0xff);
59 static inline int greyscale(byte c) {
60 return r_color(mu_color(c, c, c, 255));
64 static inline mu_Color blend_pixel(mu_Color dst, mu_Color src) {
65 int ia = 0xff - src.a;
66 dst.r = ((src.r * src.a) + (dst.r * ia)) >> 8;
67 dst.g = ((src.g * src.a) + (dst.g * ia)) >> 8;
68 dst.b = ((src.b * src.a) + (dst.b * ia)) >> 8;
69 return dst;
72 static void flush(void) {
73 // draw things based on texture, vertex, color
74 for (int i = 0; i < buf_idx; i++) {
75 mu_Rect* src = &src_buf[i];
76 mu_Rect* tex = &tex_buf[i];
77 // draw
78 int ystart = mu_max(src->y, clip_rect.y);
79 int yend = mu_min(src->y+src->h, clip_rect.y+clip_rect.h);
80 int xstart = mu_max(src->x, clip_rect.x);
81 int xend = mu_min(src->x+src->w, clip_rect.x+clip_rect.w);
82 // hacky but sufficient for us
83 if (same_size(src, tex)) {
84 for (int y = ystart; y < yend; y++) {
85 for (int x = xstart; x < xend; x++) {
86 assert(within_rect(*src, x, y));
87 assert(within_rect(clip_rect, x, y));
88 // read color from texture
89 byte tc = texture_color(tex, x-src->x, y-src->y);
90 fenster_pixel(&window, x, y) |= greyscale(tc);
93 } else {
94 mu_Color new_color = color_buf[i];
95 for (int y = ystart; y < yend; y++) {
96 for (int x = xstart; x < xend; x++) {
97 assert(within_rect(*src, x, y));
98 assert(within_rect(clip_rect, x, y));
99 // blend color from operation
100 mu_Color existing_color = mu_color_argb(fenster_pixel(&window, x, y));
101 mu_Color result = blend_pixel(existing_color, new_color);
102 fenster_pixel(&window, x, y) = r_color(result);
108 buf_idx = 0;
112 static void push_quad(mu_Rect src, mu_Rect tex, mu_Color color) {
113 if (buf_idx == BUFFER_SIZE) { flush(); }
115 tex_buf[buf_idx] = tex;
116 src_buf[buf_idx] = src;
117 color_buf[buf_idx] = color;
119 buf_idx++;
123 void r_draw_rect(mu_Rect rect, mu_Color color) {
124 push_quad(rect, atlas[ATLAS_WHITE], color);
128 void r_draw_text(const char *text, mu_Vec2 pos, mu_Color color) {
129 mu_Rect dst = { pos.x, pos.y, 0, 0 };
130 for (const char *p = text; *p; p++) {
131 if ((*p & 0xc0) == 0x80) { continue; }
132 int chr = mu_min((unsigned char) *p, 127);
133 mu_Rect src = atlas[ATLAS_FONT + chr];
134 dst.w = src.w;
135 dst.h = src.h;
136 push_quad(dst, src, color);
137 dst.x += dst.w;
142 void r_draw_icon(int id, mu_Rect rect, mu_Color color) {
143 mu_Rect src = atlas[id];
144 int x = rect.x + (rect.w - src.w) / 2;
145 int y = rect.y + (rect.h - src.h) / 2;
146 push_quad(mu_rect(x, y, src.w, src.h), src, color);
150 int r_get_text_width(const char *text, int len) {
151 int res = 0;
152 for (const char *p = text; *p && len--; p++) {
153 if ((*p & 0xc0) == 0x80) { continue; }
154 int chr = mu_min((unsigned char) *p, 127);
155 res += atlas[ATLAS_FONT + chr].w;
157 return res;
161 int r_get_text_height(void) {
162 return 18;
166 void r_set_clip_rect(mu_Rect rect) {
167 flush();
168 int ystart = mu_max(0, rect.y);
169 int yend = mu_min(window.height, rect.y+rect.h);
170 int xstart = mu_max(0, rect.x);
171 int xend = mu_min(window.width, rect.x+rect.w);
172 clip_rect = mu_rect(xstart, ystart, xend-xstart, yend-ystart);
175 void r_clear(mu_Color clr) {
176 flush();
177 for (int i = 0; i < window.width * window.height; i++) {
178 window.buf[i] = r_color(clr);
183 void r_present(void) {
184 flush();
185 fenster_loop(&window);
189 int r_mouse_down(void) {
190 if (window.mouse == 1) {
191 window.mouse++;
192 return 1;
194 return 0;
197 int r_mouse_up(void) {
198 if (window.mouse < 1) {
199 return 1;
201 return 0;
204 int r_mouse_moved(int *mousex, int *mousey) {
205 if (window.x != *mousex || window.y != *mousey) {
206 *mousex = window.x;
207 *mousey = window.y;
208 return 1;
210 return 0;
213 int r_ctrl_pressed(void) { return window.mod & 1; }
215 int r_shift_pressed(void) { return window.mod & 2; }
217 int r_alt_pressed(void) { return window.mod & 4; }
219 int r_key_down(int key) {
220 if (window.keys[key] == 1) {
221 window.keys[key]++;
222 return 1;
224 return 0;
227 int r_key_up(int key) {
228 if (window.keys[key] < 1) {
229 return 1;
231 return 0;
234 int64_t r_get_time(void) {
235 return fenster_time();
238 void r_sleep(int64_t ms) {
239 fenster_sleep(ms);