summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorDavid Thompson <dthompson2@worcester.edu>2017-01-24 20:22:09 -0500
committerDavid Thompson <dthompson2@worcester.edu>2017-01-24 21:25:21 -0500
commite46df21886b186cfcf28008eac4b9cb6577b4689 (patch)
treed80a801a4fb377f724cdb71e1d36fb39b768fd25 /doc
parent233d13ca4af2fb7627926f160b9c42638ad7b333 (diff)
doc: Document sprites and fonts.
Diffstat (limited to 'doc')
-rw-r--r--doc/api.texi183
1 files changed, 176 insertions, 7 deletions
diff --git a/doc/api.texi b/doc/api.texi
index 1524acc..554b531 100644
--- a/doc/api.texi
+++ b/doc/api.texi
@@ -414,9 +414,10 @@ blocks to implement additional rendering techniques.
@menu
* Rendering Engine:: Rendering state management.
+* Textures:: 2D images.
* Sprites:: Draw 2D images.
* Lines and Shapes:: Draw line segments and polygons.
-* Textures:: 2D images.
+* Fonts:: Drawing text.
* Blending and Depth Testing:: Control how pixels are combined.
* Vertex Arrays:: Create 2D/3D models.
* Shaders:: Create custom GPU programs.
@@ -514,12 +515,6 @@ Evaluate @var{body} with the current projection matrix bound to
@var{projection}.
@end deffn
-@node Sprites
-@subsection Sprites
-
-@node Lines and Shapes
-@subsection Lines and Shapes
-
@node Textures
@subsection Textures
@@ -539,6 +534,180 @@ coordinates that are greater than @code{1.0}. Possible values are
@end deffn
+@node Sprites
+@subsection Sprites
+
+For those who are new to this game, a sprite is a 2D rectangular
+bitmap that is rendered to the screen. For 2D games, sprites are the
+most essential graphical abstraction. They are used for drawing maps,
+players, NPCs, items, particles, text, etc. In Chickadee, bitmaps are
+stored in textures (@pxref{Textures}) and can be used to draw sprites
+via the @code{draw-sprite} procedure.
+
+@deffn {Scheme Procedure} draw-sprite @var{texture} @var{region}
+ [#:scale] [#:rotation] [#:blend-mode alpha] [#:texture-region]
+ [#:shader]
+
+@end deffn
+
+It's not uncommon to need to draw hundreds or thousands of sprites
+each frame. However, GPUs (graphics processing units) are tricky
+beasts that prefer to be sent few, large chunks of data to render
+rather than many, small chunks. Using @code{draw-sprite} on its own
+will involve at least one GPU call @emph{per sprite}, which will
+quickly lead to poor performance. To deal with this, a technique
+known as ``sprite batching'' can be used. Instead of drawing each
+sprite immediately, the sprite batch will build up a large of buffer
+of sprites to draw and defer rendering until the last possible moment.
+Batching isn't a panacea, though. Batching only works if the sprites
+being drawn share as much in common as possible. Every time you draw
+a sprite with a different texture or blend mode, the batch will be
+sent off to the GPU. Therefore, batching is most useful if you
+minimize such changes. A good strategy for reducing texture changes
+is to stuff many bitmaps into a single image file and create a
+``texture atlas'' (@pxref{Textures}) to access the sub-images within.
+
+Taking advantage of sprite batching in Chickadee is easy, just wrap
+the code that is calling @code{draw-sprite} a lot in the
+@code{with-batched-sprites} form.
+
+@deffn {Scheme Syntax} with-batched-sprites @var{body} @dots{}
+Use batched rendering for all @code{draw-sprite} calls within
+@var{body}.
+@end deffn
+
+With a basic sprite abstraction in place, it's possible to build other
+abstractions on top of it. One such example is the ``nine patch''. A
+nine patch is a sprite that can be rendered at various sizes without
+becoming distorted. This is achieved by diving up the sprite into
+nine regions:
+
+@itemize
+@item
+the center, which can be scaled horizontally and vertically
+@item
+the four corners, which can never be scaled
+@item
+the left and right sides, which can be scaled vertically
+@item
+the top and bottom sides, which can be scaled horizontally
+@end itemize
+
+The one caveat is that the bitmap regions must be designed in such a
+way so that they are not distorted when stretched along the affected
+axes. For example, that means that the top and bottom sides could
+have varying colored pixels vertically, but not horizontally.
+
+The most common application of this technique is for graphical user
+interface widgets like buttons and dialog boxes. By using a nine
+patch, they can be rendered at any size without unappealing scaling
+artifacts.
+
+@deffn {Scheme Procedure} draw-nine-patch @var{texture} @var{region}
+ [#:margin 0] [#:top-margin margin] [#:bottom-margin margin]
+ [#:left-margin margin] [#:right-margin margin]
+ [#:texture-region] [#:scale] [#:rotation] [#:blend-mode alpha]
+ [#:shader]
+
+Draw a nine patch sprite. A nine patch sprite renders @var{texture}
+as a @var{width} x @var{height} rectangle whose stretchable areas are
+defined by the given margin measurements @var{top-margin},
+@var{bottom-margin}, @var{left-margin}, and @var{right-margin}. The
+@var{margin} argument may be used to configure all four margins at
+once.
+
+Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
+the other arguments.
+@end deffn
+
+@node Lines and Shapes
+@subsection Lines and Shapes
+
+@node Fonts
+@subsection Fonts
+
+Unlike the traditional TrueType font format that many are accustomed
+to, Chickadee loads and renders bitmap fonts in the
+@url{http://www.angelcode.com/products/bmfont/doc/file_format.html,
+Angel Code format}. But why use this seemingly obscure format? It's
+easy to find TTFs but not easy to find FNTs (the canonical file
+extension used for Angel Code fonts) and bitmap fonts don't scale
+well. The reason is efficiency.
+
+If all of the glyphs of a font are pre-rendered and packed into an
+image file then it becomes possible to use a texture atlas
+(@pxref{Textures}) and a sprite batch (@pxref{Sprites}) when
+rendering, which is a more efficient way to render fonts than using,
+say, @url{https://www.libsdl.org/projects/SDL_ttf/, SDL_ttf} or other
+solutions that involve using the FreeType library directly.
+
+Now what about scaling? In libraries that use TTF fonts, one must
+choose the size that the glyphs will be rasterized at up front. To
+use @code{n} sizes of the same font, one must load @code{n} variants
+of that font. If the size of the text is dynamic, some kind of
+texture scaling algorithm must be used and the text will inevitably
+look blurry. At first glance, using bitmap fonts seem to have an even
+worse issue. Instead of just loading the same font @code{n} times at
+different sizes, one would need to generate @code{n} image files for
+each font size needed. This is where the ``signed distance field''
+rendering technique comes in. Introduced by
+@url{http://www.valvesoftware.com/.../2007/SIGGRAPH2007_AlphaTestedMagnification.pdf,
+Valve} in 2007, signed distance field fonts can be efficiently stored
+in a bitmap and be rendered at arbitrary scale factors with good
+results. Chickadee can render both traditional bitmap fonts and
+signed distance field fonts.
+
+While Chickadee does not yet offer a tool for converting TTF fonts
+into FNT fonts, tools such as
+@url{https://github.com/libgdx/libgdx/wiki/Hiero, Hiero} may be used
+in the meantime.
+
+The following procedures can be found in the @code{(chickadee render
+font)} module.
+
+@deffn {Scheme Procedure} load-font @var{file}
+Load the Angel Code formatted XML document in @var{file} and return a
+new font object.
+@end deffn
+
+@deffn {Scheme Procedure} font? @var{obj}
+Return @code{#t} if @var{obj} is a font object.
+@end deffn
+
+@deffn {Scheme Procedure} font-face @var{font}
+Return the name of @var{font}.
+@end deffn
+
+@deffn {Scheme Procedure} font-line-height @var{font}
+Return the line height of @var{font}.
+@end deffn
+
+@deffn {Scheme Procedure} font-line-height @var{font}
+Return the line height of @var{font}.
+@end deffn
+
+@deffn {Scheme Procedure} font-bold? @var{font}
+Return @code{#t} if @var{font} is a bold font.
+@end deffn
+
+@deffn {Scheme Procedure} font-italic? @var{font}
+Return @code{#t} if @var{font} is an italicized font.
+@end deffn
+
+@deffn {Scheme Procedure} draw-text @var{font} @var{text} @var{position}
+ [#:scale] [#:rotation] [#:blend-mode]
+
+Draw the string @var{text} with the first character starting at
+@var{position} using @var{font}.
+
+@example
+(draw-text font "Hello, world!" (vec2 128.0 128.0))
+@end example
+
+Refer to @code{draw-sprite} (@pxref{Sprites}) for information about
+the other arguments.
+@end deffn
+
@node Blending and Depth Testing
@subsection Blending and Depth Testing