1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
|
* Tasks
** TODO [#B] Bytestruct -> vertex layout conversion
** TODO [#C] Add mesh primitive for 2D/3D quads
** TODO [#C] Rename some matrix procedures
matrix4-mult! -> matrix4-mul!
matrix4* -> matrix4:*
matrix4= -> matrix4=?
ditto for matrix3
** TODO [#A] Add define-script syntax
isaneran on #guile said that they were re-evaluating top-level
definitions with geiser that contained a script value, and when they
did that they lost the reference to the old script. Sometimes this
means old and new scripts are running at the same time but there's no
way to cancel the old since the reference is no longer accessible. A
=define-script= form that checks if the variable is defined and a
script first would help here, as it could cancel the old script before
starting the new one.
** TODO [#A] Set proper load path when launching chickadee script
Add the installation location to GUILE_LOAD_PATH and
GUILE_LOAD_COMPILED_PATH, as determined at configure time, to the
chickadee script so that the script "just works" without the user
having to setup load paths in a certain way.
** TODO [#A] Clarfiy that 'chickadee play' starts game loop for you
ekaitz and wklew have both been confused why 2 windows open up when
they try to use 'chickadee play'. The docs don't make it clear that
they don't have to call 'run-game' when using 'chickadee play'.
Also, update the examples to be run with 'chickadee play' because
people copy/paste them and wonder why they don't just work!
** TODO [#A] Rewrite renderer
It is finally time to make Chickadee at least theoretically capable of
using a graphics API other than OpenGL. OpenGL is showing its age and
all newer graphics APIs use a stateless render queue approach that is
much better than OpenGL's awful global state. MacOS doesn't support
anything past OpenGL 3 and there's already been a number of
compatibility issues for Chickadee. WebGPU is quickly becoming a
thing and with Guile Hoot on the horizon it should be possible to ship
Chickadee games in the browser that use modern graphics APIs, but the
work to make that happen needs to start now. So, the goal is to move
all OpenGL code to an OpenGL backend, add support for multiple
backends, and expose a WebGPU-like interface since the team who made
it have already done the hard work of abstracting over Vulkan, Metal,
and Direct3D. When we can target the web via Hoot, our graphics
backend will be a thin wrapper over the WebGPU JS API, more or less.
And of course on native targets we will now have the option of using
whatever graphics API makes the most sense.
Some big subtasks here:
- [ ] Decouple OpenGL state management from dynamic render context
- [ ] Refactor all OpenGL calls into a single module
- [ ] Add generic WebGPU-like graphics API
- [ ] Implement that API for OpenGL backend
- [ ] Update all graphics modules to use new API
One big caveat is that our shading language will still be GLSL at the
end of this, which prevents us from being truly generic. The Seagull
shading language project will take care of that so we can compile to
whichever shader language our backend uses.
See this for how Trial does graphics pipelines:
https://reader.tymoon.eu/article/363
** TODO [#A] Move game logic to its own thread
The main thread should be reserved for running the game loop,
processing the input queue, and processing the render queue.
** TODO [#A] Switch from OpenAL to SDL2 audio
I've decided that OpenAL is too high level to be a library that
Chickadee should rely upon, since part of the goal of Chickadee is to
implement as much as possible in Scheme and only resort to C if
absolutely necessary. OpenAL will also make it more difficult to ship
games on the web using Web Audio when Hoot is ready (no I am not going
to compile OpenAL with emscripten.) Instead, we can use SDL2's
cross-platform audio API and implement all the audio mixing directly
in Scheme in a dedicated audio thread.
** TODO [#A] Improve error messages in sprite-batch-add!
=sprite-batch-add!= throws an error if it is called before
=sprite-batch-clear!= maps the GPU memory, but the error message
doesn't mean anything to users. Also, make sure the docs explain why
you need to clear first. Consider renaming =sprite-batch-clear!= to
=sprite-batch-begin!= while you're at it. Explain the difference
between capacity and size.
** TODO [#A] Bug: Bundled games don't close properly?
The window goes black but doesn't close. Closing the window again
actually closes it.
** TODO [#B] Remove allocations in hot code paths
- [ ] hash-for-each causes closure allocation in at least the shader,
text, and audio modules
- [ ] call-with-error-handling in (chickadee game-loop) allocates
closures and is called twice per loop iteration.
** TODO [#B] Bug: Vertical line rendering not working
Vertical lines are invisible. Not great!
** TODO [#B] The Seagull Shading Language
Like CL's varjo but for Scheme! The goal here is to stop exposing
GLSL to users. For one thing, GLSL sucks to write when you're a
Lisper. If you want to embed a shader in a Scheme module, it has to
be in a gross multi-line string literal. It also tightly couples
Chickadee to OpenGL, but ideally we want to be graphics API agnostic.
By using a Schemey shader language we get something that composes well
with regular Scheme code while also opening up the possibility of
targetting modern graphics APIs in the future.
Goals:
- Scheme-like syntax
- Embeddable within Scheme source files
- Compiles to GLSL (for now)
- Clean interface for passing data from Scheme to shaders
- Implicit returns in tail position (no 'return' keyword)
- Everything is an expression
- Type inference
- Understands built-in shader stage variables
- See: https://www.khronos.org/opengl/wiki/Built-in_Variable_(GLSL)
- Macros
- Nested functions if they don't form closures
- Shader libraries for reusing and composing code
#+BEGIN_SRC scheme
;; Input vertices are positional arguments, uniforms are keyword
;; arguments.
(define (sprite-vertex (vec2 position) (vec2 tex) #:key (mat4 mvp))
;; First argument returned is the vertex position, all others get
;; mapped to fragment shader inputs.
(values (* mvp (vec4 (-> position x) (-> position y) 0.0 1.0))
tex))
(define (sprite-fragment (vec2 )))
#+END_SRC
** TODO [#B] Uniform buffers
Need some way to support these while falling back to the current, slow
way that is compatible with OpenGL 2.1.
** TODO [#B] Ditch the readline dependency
Figure out how to get back to using Guile's built-in REPL for
=chickadee play= so the custom can go away. Readline is hard to make
work in an async manner.
** TODO [#B] Bug: Framebuffer stencil issues
Render a vector path to a framebuffer and you'll notice that the first
filled path doesn't show up. Why is this??
** TODO [#B] Framebuffer multisampling
Requires creating multisampled texture.
** TODO [#B] Add screenshots to manual
** TODO [#C] Add shear transformations to vector paths
** TODO [#C] Dashed lines for stroked vector paths
** TODO [#C] Mitered corners for stroked vector paths
** TODO [#C] Even-odd rule fills for vector paths
Right now only the non-zero rule is supported.
** TODO [#C] Reverse winding order for vector paths
** TODO [#C] Text rendering for vector paths
** TODO [#C] Texture fills for vector paths
** TODO [#C] Improve particle system
Allow more settings to be modified. Add angular velocity.
Auto-expand to hold all particles rather than setting a hard cap
upfront.
** TODO [#C] Support loading fonts from system font cache
** TODO [#C] REPL meta-command for rendering to an image file
=,render-image= or something. Use a throwaway framebuffer to render
arbitrary stuff to a texture and then save it as a PNG.
** TODO [#C] Rename array-list-size to array-list-length
** TODO [#C] Bug: Bounding boxes for stroked paths are too small
Not sure how to fix right now but the bounding boxes are too small
because they only account for the points within a path, not the
thickness of the line, the length of the miters in a polyline, or the
end caps.
** TODO [#C] Shader cache in ~/.cache/chickadee?
** TODO [#C] Binary bundles for MacOS
** TODO [#C] 2D physics simulation
Add bindings for the chipmunk library or implement a rigid body
simulator in Scheme.
** TODO [#C] Multiplayer networking
Take a look at Xelf's UDP networking code and https://gafferongames.com/categories/building-a-game-network-protocol/
** TODO [#C] Signed distance field font rendering
** TODO [#C] Physically-based ambient lighting
The PBR shader currently does image based ambient lighting in a very
naive way that does not use physically-based equations.
** TODO [#C] Right-to-left text rendering
** TODO [#C] Top-to-bottom text rendering
** TODO [#C] Octree spatial partitioning
** DONE [#A] Mention (chickadee-user) module in 'chickadee play' docs
When you connect to the REPL server, it's in (guile-user) but there's
nothing telling the user to switch to the right default place. Can we
make the REPL automatically go to the right module?
** DONE [#A] Improve window resizing support
For example, there's no user hook to handle a resize event.
** DONE [#A] Images that can be rendered in Geiser REPL
Make =<image>= type that prints as =#<Image: /path/to/image.png>=
** DONE [#A] CPU-side pixel buffer manipulation
Make =<pixbuf>= type and use it for all image loading/manipulation,
such as texture creation.
** DONE [#A] Fix 9-patch rendering not working with texture regions
** DONE [#A] Add #:clear-color argument to run-game
** DONE [#A] Tests for (chickadee math rect)
** DONE [#A] Add matrix{3,4}-copy! procedures
** DONE [#A] Load palleted PNGs
** DONE [#A] Remove SDL2-image dependency
Directly link against libpng and libjpeg-turbo, for starters. Support
for other formats can be added later. This will give us more
flexibility since we won't be tied to SDL surfaces and thus a single
thread for image loading.
** DONE [#A] Fix keyboard layout bug
For example, someone with a QWERTZ keyboard layout, when they press
their Z key, will invoke the key-press handler with the Z key, but
(key-pressed? 'z) will be false and (key-pressed? 'y) will be true.
** DONE [#B] Quadtree spatial partitioning
** DONE [#B] Add arc-to procedure for vector paths
** DONE [#A] Tests for (chickadee data array-list)
** DONE [#A] Tests for (chickadee data heap)
** DONE [#A] Tests for (chickadee data queue)
** DONE [#A] Update rendering engine docs
** DONE [#A] Update live coding section of manual
** DONE [#A] Document polygon, cull face, depth test, stencil modes
** DONE [#A] Document cube map texture procedures
** DONE [#A] Document materials, lights, and meshes
** DONE [#A] Add intensity field to lights
** DONE [#A] Test suite
** DONE [#A] Binary bundles for Linux
For easy distribution of builds so players don't have to build
anything from source.
** DONE [#A] Mipmapping
** DONE [#A] Skyboxes
** DONE [#A] Basic 3D shape primitives
Plane, tesselated plane, sphere, cube
** DONE [#A] Image based lighting for 3D models
Cube maps and such. See:
https://learnopengl.com/PBR/IBL/Diffuse-irradiance
** DONE [#A] Reimplement 9-patches
** DONE [#A] Chunk-based tile map rendering
** DONE [#A] Render rotated tiles in Tiled maps correctly
See STIB library for love2d for implementation details.
** DONE [#A] Render animations in Tiled maps
** DONE [#A] Support modifications to Tiled maps
** DONE [#A] Handle window resizing gracefully
** DONE [#A] Display clear error when using OpenGL before game loop has been started
** DONE [#A] Macro for looping over number ranges
Get rid of all the dang named lets for looping over x and y values in
a grid.
** DONE [#A] High-level vertex buffer packing API
Filling vertex buffers by hand sucks and leads to lots of redundant,
brittle code all over the place. Especially so for anything that does
vertex buffer streaming like sprite batches and vector paths. Maybe
copy something like guile-opengl's packed structs.
** DONE [#A] Front/back face culling support
** DONE [#A] Vector graphics rendering
Like NanoVG.
** DONE [#A] Feature request: Support color keyed tilesets in Tiled maps
** DONE [#A] Bug fix: Clear screen even when nothing is being drawn
** DONE [#A] Allow user to manipulate the current window
** DONE [#A] OBJ model loader and renderer
** DONE [#A] Fix bugs/missing features in particle renderer
** DONE [#A] Document how to hook up cooperative REPL server
** DONE [#A] Document (chickadee graphics tiled) module
** DONE [#A] Add pixel x,y to tile x,y procedure for Tiled maps
** DONE [#A] TrueType font rendering
Like love2d or NanoVG
** DONE [#A] Chickadee executable
Like love2d's =love= executable. For getting new users up and running
quickly.
** DONE [#B] Linear/radial gradient fills for vector paths
** DONE [#B] Improved blending API
Rather than using symbols to represent some predefined blending modes,
create an api that supports the full range of options that OpenGL
provides for defining the blending function.
** DONE [#B] Tile map scrolling
** DONE [#B] OpenAL sound
Better than SDL_mixer. For love2d parity.
** DONE [#B] glTF 2.0 asset loading
Partially implemented but most example models don't render correctly.
** DONE [#C] Rewrite GPU state and render context code
Adding a new piece of state requires too much work, much of which
feels redundant.
** DONE [#C] Improve technique-specific state handling
Right now everything (shaders, buffers, etc.) is wrapped in 'delay'
forms and then 'force'd when rendering. It would be better if we
could somehow register this stuff with the gpu object. A plugin
system, maybe. The plugins would be initialized when the gpu object
is created and all the state would live there instead of at the
top-level of various modules.
** DONE [#C] Physically based rendering
Needed for full glTF rendering support but just good in general for
3D.
|