aboutsummaryrefslogtreecommitdiff
path: root/posts
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-03-17 12:29:43 +0000
committerAkshay <[email protected]>2021-03-17 12:29:43 +0000
commit3e0f620a933cf2a9325d051e87952edb1c3f9270 (patch)
tree8e18948f6f48bf0e64571febc99fdc0d976aad62 /posts
parent6ae6d2e458747cf5a30f204c727d45121ff3e8e4 (diff)
new post: sdl2 devlog
Diffstat (limited to 'posts')
-rw-r--r--posts/SDL2_devlog.md139
1 files changed, 139 insertions, 0 deletions
diff --git a/posts/SDL2_devlog.md b/posts/SDL2_devlog.md
new file mode 100644
index 0000000..0b05c90
--- /dev/null
+++ b/posts/SDL2_devlog.md
@@ -0,0 +1,139 @@
1I have been working on an editor for the [One Bit
2Image](https://git.peppe.rs/graphics/obi/about) file format in
3Rust and SDL2. This entry in my blog follows my progress on
4the editor. The days are listed in reverse chronological
5order, begin from the bottom this is your first time on this
6page.
7
8### Day 10
9
10I started reading up on dithering methods and half-toning, I
11wanted to create a dithering brush that would automatically
12produce popular dithering patterns. The method that caught
13my eye (and also the one used most often in pixel art), was
14Bayer's ordered dithering. When applied to a black and white
15image, each pixel, based on its intensity, is mapped to a
164x4 grid of pixels. A completely empty (completely black)
174x4 grid represents zero intensity, and a filled 4x4 grid
18represents full intensity. Bayer's ordered dithering can
19produce 15 steps of intensity between zero and full (by
20switching on exactly 1 pixel more at each level), thus,
21being able to draw 17 "shades" from white to black. Creating
22a dithering brush from here was fairly trivial. Our pixmap
23is supposed to represent the final dithered image, it must
24be divided into 4x4 grids. Each grid is colored based on the
25intensity of the brush passing over it:
26
27![Day 10](https://u.peppe.rs/Mn.png)
28
29
30### Day 9
31
32I started working towards an interface. I like the idea of a
33largely read-only HUD, i. e., an interface that simply
34describes the state of the application. Changes to this
35state are initiated via keybinds or text commands. I am
36proud of the symmetry indicator; `-` for horizontal
37symmetry, `|` for vertical symmetry, `+` for radial
38symmetry.
39
40![Day 9](https://u.peppe.rs/hx.png)
41
42### Day 8
43
44One of my favourite features of GIMP was symmetric editing.
45I added some coordinate geometry primitives to my pixmap
46abstraction, allowing for mirroring and reflecting figures
47about lines or points. The result was an ergonomic function
48that applies symmetry to any painting operation, (undo/redo
49works as expected):
50
51```rust
52let line = self.pixmap.get_line(start, end);
53let sym_line = self.symmetry.apply(&line);
54for point on line.extend(sym_line) {
55 // draw to window
56}
57```
58
59![Day 8](https://u.peppe.rs/B1.mp4)
60
61### Day 7
62
63Bresenham saves the day again! This time, I implemented his
64line drawing algorithm, to, well, draw lines. Each point on
65the line is then "buffed" based on the active brush size.
66Today's changes fit in very well with the undo system and
67the brush size feature. Creating the right abstractions, one
68at a time :)
69
70![Day 7](https://u.peppe.rs/xt.mp4)
71
72
73### Day 6
74
75I extended Bresenham's algorithm to draw not just circle
76outlines, but also generate their fills. Unlike Bresenham's
77algorithm, this variant generates points for two quadrants
78at once, these points are mirrored over the dividing axis to
79generate the other two quadrants.
80
81![Day 6](https://u.peppe.rs/f3.png)
82
83### Day 5
84
85I discovered and implemented Bresenham's algorithm for
86efficient circle drawing. The algorithm allowed for sized
87circular brushes, something I really liked from GIMP. Very
88convenient that the Wikipedia page for Bresenham's algorithm
89also includes a section about optimizing for integer based
90arithmetic. I managed to abstract out another giant
91component of the application, the pixmap. Any image is just
92a grid of pixels (a pixmap), where the pixel's value is
93decided by the application (1-bit in my case). I could
94potentially extend the application to a 24-bit image editor!
95
96![Day 5](https://u.peppe.rs/Kh.mp4)
97
98
99### Day 4
100
101I created a generic "undo stack" data structure that allows
102for infinite "undos" and "redos". Every modification
103operation to the grid is persisted to the application state.
104A couple of keybinds allow the user to revert and re-apply
105these operations! I expect abstracting this component will
106come in handy down the line.
107
108![Day 4](https://u.peppe.rs/w5.mp4)
109
110
111### Day 3
112
113I implemented the bare minimum required to call the program
114and "editor". The application displays a grid, tracks mouse
115events, paints white to the canvas on left click, and black
116to the canvas on right click. I created a make-shift MVC
117architecture à la Elm in Rust.
118
119![Day 3](https://u.peppe.rs/GF.mp4)
120
121### Day 2
122
123I started figuring out event handling today. Implemented a
124couple of keybinds to zoom in/out of the drawing area.
125Conversions of SDL2 coordinates (measured in signed 32 bit
126integers) to my internal "drawing area" coordinates
127(measured in unsigned 32 bit integers) is very annoying.
128Hopefully the unchecked conversions won't haunt me later.
129
130![Day 2](https://u.peppe.rs/L4.mp4)
131
132### Day 1
133
134Getting started with Rust and SDL2 is very straightforward.
135The `rust-sdl2` library contains some detailed examples that
136allowed me to get all the way to drawing a grid from a
137`Vec<bool>`:
138
139![Day 1](https://u.peppe.rs/Ma.png)