OSDN Git Service

Working on README, put defs in joy.py
[joypy/Thun.git] / implementations / uvm-ncc / graphics.h
1 #include <assert.h>
2 #include <stddef.h>
3
4 #define   RED 0xFF_00_00
5 #define GREEN 0x00_FF_00
6 #define WHITE 0xFF_FF_FF
7
8 void
9 draw_background(u32* buffer, size_t w, size_t h)
10 {
11         for (size_t x = 0; x < w; ++x) {
12                 for (size_t y = 0; y < h; ++y) {
13                         u8 blue = x & 255;
14                         u8 green = y & 255;
15                         u8 red = (x + y + 128) & 255;
16                         u32* pix_ptr = buffer + w * y + x;
17                         *pix_ptr = (red << 16) | (green << 8) | blue;
18                 }
19         }
20 }
21
22 void
23 draw_cicada_bars_background(u32* buffer, size_t w, size_t h)
24 {
25         for (size_t x = 0; x < w; ++x) {
26                 for (size_t y = 0; y < h; ++y) {
27                         u8 blue  = 5*x%17 + 127;
28                         u8 green = 5*x%37 + 127;
29                         u8 red   = 5*x%43 + 127;
30                         u32* pix_ptr = buffer + w * y + x;
31                         *pix_ptr = (red << 16) | (green << 8) | blue;
32                 }
33         }
34 }
35
36
37 void
38 draw_cicada_bars_background0(u32* buffer, size_t w, size_t h)
39 {
40         for (size_t x = 0; x < w; ++x) {
41                 for (size_t y = 0; y < h; ++y) {
42                         u8 blue  = !((5*x / 17) & 1) ? 100 : 0;
43                         u8 green = !((5*x / 37) & 1) ? 100 : 0;
44                         u8 red   = !((5*x / 43) & 1) ? 100 : 0;
45                         u32* pix_ptr = buffer + w * y + x;
46                         *pix_ptr = (red << 16) | (green << 8) | blue;
47                 }
48         }
49 }
50
51 void
52 carefree_alpha_blend_blit(u32* dest, u32* source, size_t dest_stride, u64 dest_x, u64 dest_y, u64 w, u64 h)
53 {
54         u32* d = dest + dest_stride * dest_y + dest_x;
55         for (u64 y = 0; y < h; ++y) {
56                 for (u64 x = 0; x < w; ++x) {
57                         u32* spix_ptr = source + x + w * y;
58                         u32 pixel = *spix_ptr;
59                         u8 alpha = pixel >> 24;
60                         if (!alpha) continue;
61                         u32* pix_ptr = d + x + dest_stride * y;
62                         if (0xFF == alpha) {
63                                 *pix_ptr = pixel;
64                                 continue;
65                         }
66                         u32 dest_pixel = *pix_ptr;
67                         u8 unalpha = 0xFF - alpha;
68                         u8 red = (((dest_pixel >> 16) & 255) * unalpha + ((pixel >> 16) & 255) * alpha) / 0xff;
69                         u8 green = (((dest_pixel >> 8) & 255) * unalpha + ((pixel >> 8) & 255) * alpha) / 0xff;
70                         u8 blue = ((dest_pixel & 255) * unalpha + (pixel & 255) * alpha) / 0xff;
71                         *pix_ptr = (alpha << 24) | (red << 16) | (green << 8) | blue;
72                 }
73         }
74 }
75
76
77 void
78 carefree_draw_horizontal_line(u32* dest, size_t dest_stride, u64 x, u64 y, u64 w, u32 color)
79 {
80         u32* d = dest + dest_stride * y + x;
81         for (u64 i = 0; i < w; ++i) {
82                 *d = color;
83                 d = d + 1;
84         }
85 }
86
87
88 void
89 carefree_draw_vertical_line(u32* dest, size_t dest_stride, u64 x, u64 y, u64 h, u32 color)
90 {
91         u32* d = dest + dest_stride * y + x;
92         for (u64 i = 0; i < h; ++i) {
93                 *d = color;
94                 d = d + dest_stride;
95         }
96 }
97
98
99 void
100 carefree_draw_box(u32* dest, size_t dest_stride, u64 y, u64 x, u64 w, u64 h, u32 color)
101 {
102         carefree_draw_horizontal_line(dest, dest_stride, x,     y,     w, color);
103         carefree_draw_horizontal_line(dest, dest_stride, x,     y + h, w, color);
104         carefree_draw_vertical_line(  dest, dest_stride, x,     y,     h, color);
105         carefree_draw_vertical_line(  dest, dest_stride, x + w, y,     h, color);
106 }
107
108
109 void
110 carefree_alpha_blend_plot_pixel(u32* dest, size_t dest_stride, u64 x, u64 y, u32 color, u8 alpha)
111 {
112         if (!alpha) return;
113         u32* pix_ptr = dest + dest_stride * y + x;
114         if (0xFF == alpha) {
115                 *pix_ptr = color;
116                 return;
117         }
118         u32 dest_pixel = *pix_ptr;
119         u8 unalpha = 0xFF - alpha;
120         u8 red = (((dest_pixel >> 16) & 255) * unalpha + ((color >> 16) & 255) * alpha) / 0xff;
121         u8 green = (((dest_pixel >> 8) & 255) * unalpha + ((color >> 8) & 255) * alpha) / 0xff;
122         u8 blue = ((dest_pixel & 255) * unalpha + (color & 255) * alpha) / 0xff;
123         *pix_ptr = (red << 16) | (green << 8) | blue;
124 }
125
126
127 void
128 carefree_wu_line(u32* dest, size_t dest_stride, u64 x, u64 y, u64 w, u64 h, u32 color)
129 {
130         // This isn't quite Wu's algorithm, although it uses the same
131         // fundamental trick of keeping track of both the intensity of
132         // the pixels to draw and the right time to increment the minor
133         // axis in a single error term.
134         //
135         // "An Efficient Antialiasing Technique", Xiaolin Wu
136         // Computer Graphics, Volume 25, Number 4, July 1991
137         // https://dl.acm.org/doi/pdf/10.1145/127719.122734
138         //
139         // "Graphics Programming Black Book" by Michael Abrash, chapter 42
140         // https://archive.org/details/gpbb20
141
142         // > Without loss of generality only lines in the first octant are considered.
143         assert(w > 0 && h > 0 && w > h);
144
145         // > We translate the point (x0, y0) to the origin,
146         // so y = kx where k = h/w with k <= 1
147         // (actually k < 1 because 45° lines are special-cased.)
148         u16 k = 0xFFFF * h / w;
149         u16 d = k >> 1;
150         while (w) {
151                 w = w - 1;
152                 u8 intensity = d >> 8;
153                 carefree_alpha_blend_plot_pixel(dest, dest_stride, x, y + 1, color,  intensity);
154                 carefree_alpha_blend_plot_pixel(dest, dest_stride, x, y,     color, 0xFF - intensity);
155                 ++x;
156                 if (d + k >= 0xFFFF) {
157                         d = k - (0xFFFF - d);
158                         ++y;
159                 } else {
160                         d = d + k;
161                 }
162         }
163 }
164