The size of one texel in bytes, or 0 for the block compressed formats.
assert(get_image_bytes_per_texel(.RGBA16F) == 8);
assert(get_image_bytes_per_texel(.BC1) == 0);↗#import "Simp";
A small 2D renderer on OpenGL: coloured shapes, textures, text and render targets, drawn through immediate-mode calls.
Make a window with Window_Creation, choose it with set_render_target, then each frame call
update_window, clear_render_target, draw, and swap_buffers. Pick a shader first
(set_shader_for_color or set_shader_for_images), then draw with immediate_quad, or send
single corners with immediate_vertex. load_font and draw_text put text on screen. Textures come
from texture_load_from_file or texture_load_from_memory.
The default coordinate system has its origin at the bottom left with y growing up; pass
.LEFT_HANDED to set_render_target for the top left with y growing down.
#import "Window_Creation";
#import "Input";
window := create_window(800, 600, "simp");
set_render_target(window);
font := load_font("", "Roboto-Regular.ttf", 24);
while true {
update_window_events();
for events_this_frame if it.type == .QUIT return;
update_window(window);
clear_render_target(0.1, 0.1, 0.15, 1);
set_shader_for_color();
immediate_quad(100, 100, 300, 200, .{0.9, 0.3, 0.2, 1});
draw_text(font, 100, 300, "Hello");
swap_buffers(window);
}This one is only checked to compile, not run.
.NONE draws nothing.The size of one texel in bytes, or 0 for the block compressed formats.
assert(get_image_bytes_per_texel(.RGBA16F) == 8);
assert(get_image_bytes_per_texel(.BC1) == 0);↗The size of a 4 by 4 block of a compressed format in bytes. Asserts for formats that aren't block compressed.
The bytes an image of this format and size takes, and the bytes in one row (or one row of blocks).
size, stride := get_image_size(.RGBA8, 10, 5);
assert(size == 200 && stride == 40);
size, stride = get_image_size(.BC1, 10, 5); // 3 x 2 blocks of 8 bytes
assert(size == 48 && stride == 24);↗Gives bitmap pixel storage of the given size and format, freeing what it held. The bitmap owns the
memory: free it with deinit.
bitmap: Bitmap;
bitmap_alloc(*bitmap, 8, 8, .R8);
defer deinit(*bitmap);
assert(bitmap.data.count == 64);↗Frees the bitmap's pixels if it owns them, and empties it.
Replaces the bitmap's pixels with the same image followed by each half-size level, down to 1 by 1.
Reads an image file into bitmap. Returns false when the file is missing or is not an image.
bitmap: Bitmap;
if !bitmap_load(*bitmap, "sprite.png") return;
defer deinit(*bitmap);This one is only checked to compile, not run.
Like bitmap_load, for an image that is already in memory.
#import "Extensions/Image";
png := encode_png(make_image(2, 2, .RGB8));
defer free(png.data);
bitmap: Bitmap;
assert(bitmap_load_from_memory(*bitmap, png));
defer deinit(*bitmap);
assert(bitmap.width == 2 && bitmap.format == .RGB8);↗Writes bitmap to an image file. Returns false for any other extension, for a bitmap that is not RGB8 or RGBA8, or when the write fails.
bitmap: Bitmap;
bitmap_alloc(*bitmap, 16, 16, .RGB8);
defer deinit(*bitmap);
bitmap_save(*bitmap, "out.png");This one is only checked to compile, not run.
Starts FreeType and optionally sets the size of the glyph atlas pages (at least 64 by 64). Fonts start it on first use.
Starts FreeType if it isn't running.
The font already loaded from this file name, or null.
Reads a font from memory and registers it under name. The bytes must outlive the font.
Frees a loaded font.
Loads a font file at a size, reusing the font if it was loaded at that size before. Returns null if the file can't be read.
Loads a font file at one size. Returns null when the file cannot be read.
font := load_font("fonts", "Roboto-Regular.ttf", 24);
if !font return;This one is only checked to compile, not run.
Lets go of a font. Fonts and their glyph atlases are kept for reuse, so this is cheap.
Picks the character drawn for code points the font lacks. Returns false if the font doesn't have utf32.
The distance from the top of a line to its baseline, in pixels.
How far the pen moves after glyph, in pixels.
The width in pixels of the one UTF-8 character at utf8. A byte sequence that is not valid counts as the font's unknown character.
font := load_font("", "Roboto-Regular.ttf", 24);
width := get_character_width_in_pixels(font, "W".data, 0);This one is only checked to compile, not run.
Lays text out and returns its width in pixels. draw_prepared_text then draws it.
font := load_font("", "Roboto-Regular.ttf", 24);
width := prepare_text(font, "Game over");
draw_prepared_text(font, (800 - width) / 2, 300); // centredThis one is only checked to compile, not run.
Starts a run of text for append_prepare_text. Use it, with end_prepare_text, to join pieces that
prepare_text can't take in one string.
Adds the glyphs of s to the run; byte offsets count from the start of this piece.
font := load_font("", "Roboto-Regular.ttf", 24);
begin_prepare_text(font);
append_prepare_text(font, "Hello, ");
append_prepare_text(font, "world");
end_prepare_text(font);This one is only checked to compile, not run.
Closes the run and lays its glyphs out as font.current_quads, with the pen at the origin and the
baseline at y = 0. draw_prepared_text draws the same run wherever you like.
Uploads bitmap to the graphics card as texture. Returns false when that fails.
bitmap: Bitmap;
bitmap_alloc(*bitmap, 16, 16, .RGBA8);
defer deinit(*bitmap);
texture: Texture;
assert(texture_load_from_bitmap(*texture, *bitmap));This one is only checked to compile, not run.
Reads an image file and uploads it as map. Returns false when it cannot read or decode the file.
texture: Texture;
if !texture_load_from_file(*texture, "sprite.png", srgb = true, build_mipmaps = true) return;This one is only checked to compile, not run.
Like texture_load_from_file, for an image that is already in memory.
#import "File";
file := read_entire_file("sprite.png");
texture: Texture;
if !texture_load_from_memory(*texture, cast([] u8) file) return;This one is only checked to compile, not run.
Chooses how texture is sampled when drawn at another size.
Frees the texture's storage on the graphics card.
Makes an empty texture that can be drawn into: make it current with set_render_target, then draw as usual.
#import "Window_Creation";
window := create_window(800, 600, "simp");
target := texture_create_render_target(512, 512, .RGBA8);
set_render_target(*target);
// ... draw ...
set_render_target(window);
// now draw `target` like any textureThis one is only checked to compile, not run.
Whether the graphics card can use a texture of this format.
Compiles a shader from its source text and returns the GL program, or 0 if it doesn't compile.
Sets a matrix uniform of a shader by name.
Chooses where drawing goes, and what the coordinates mean. Anything drawn so far is flushed first.
#import "Window_Creation";
window := create_window(800, 600, "simp");
set_render_target(window, .LEFT_HANDED);This one is only checked to compile, not run.
Tells Simp the window may have changed size or scale. Call it once per frame before drawing.
The size of the window's drawing area in window units.
The size of the window's framebuffer in device pixels.
#import "Window_Creation";
window := create_window(800, 600, "simp");
width, height := get_pixel_dimensions(window);This one is only checked to compile, not run.
Device pixels per window coordinate unit (2 on a Retina display).
#import "Window_Creation";
window := create_window(800, 600, "simp");
scale := get_pixel_scale(window); // 2 on a Retina displayThis one is only checked to compile, not run.
Stops Simp from drawing to window. Calls that would draw to it do nothing until enable_window.
Lets Simp draw to window again after disable_window.
Shows what was drawn to window. Anything still batched is drawn first.
#import "Window_Creation";
window := create_window(800, 600, "simp");
set_render_target(window);
clear_render_target(0, 0, 0, 1);
swap_buffers(window);This one is only checked to compile, not run.
Fills the current render target with one colour, and clears its depth and stencil.
clear_render_target(0.1, 0.1, 0.15, 1);This one is only checked to compile, not run.
Limits drawing to a box, in the coordinates of the current render target.
set_scissor(.{10, 10}, .{110, 60});
// ... draw: only this box shows ...
clear_scissor();This one is only checked to compile, not run.
Lifts the limit set by set_scissor.
set_scissor(0, 0, 100, 100);
clear_scissor();This one is only checked to compile, not run.
Throws away the corners waiting in the batch without drawing them.
Starts a new batch. It does the same as immediate_reset.
Draws the batch now. Switching shader or texture, swap_buffers and a full batch do this on their own.
Selects the shader for the next corners, drawing the batch first if the shader changes.
Selects the texture for the next corners, drawing the batch first if the texture changes.
Adds one corner to the batch. Every three corners make a triangle, and the batch is drawn when it fills or when something forces a flush.
set_shader_for_color();
#import "Math";
red := Vector4.{1, 0, 0, 1};
immediate_vertex(.{100, 100, 0}, red);
immediate_vertex(.{200, 100, 0}, red);
immediate_vertex(.{150, 200, 0}, red); // a triangleThis one is only checked to compile, not run.
Sends the current projection to the current shader.
Draws the following triangles in plain colours, with no texture.
set_shader_for_color(enable_blend = true);
immediate_quad(10, 10, 110, 60, .{0, 0.5, 1, 0.5});This one is only checked to compile, not run.
Draws the following triangles with texture, scaled by their colours.
texture: Texture;
texture_load_from_file(*texture, "sprite.png");
set_shader_for_images(*texture);
immediate_quad(.{10, 10}, .{138, 10}, .{138, 138}, .{10, 138});This one is only checked to compile, not run.
Draws text in one line and returns its width in pixels.
font := load_font("", "Roboto-Regular.ttf", 24);
width := draw_text(font, 20, 40, "Score: 120", .{1, 1, 0, 1});This one is only checked to compile, not run.
Draws the text last given to prepare_text, so a text drawn many times is laid out once.
font := load_font("", "Roboto-Regular.ttf", 24);
prepare_text(font, "Paused");
draw_prepared_text(font, 20, 40);
draw_prepared_text(font, 20, 80, .{1, 0.5, 0.5, 1});This one is only checked to compile, not run.
Adds a triangle to the batch, with a colour and texture coordinate for each corner.
Adds a rectangle from two corners, in one colour.
set_shader_for_color();
immediate_quad(10, 10, 110, 60, .{1, 1, 1, 1});This one is only checked to compile, not run.
Starts copying the pixels of source back to the CPU without waiting for them. Poll with pixel_read_is_done, then collect them with pixel_read_end.
target := texture_create_render_target(256, 256, .RGBA8);
reader := pixel_read_begin(*target, .RGBA8, flip = true);
while !pixel_read_is_done(reader) {}
bitmap := pixel_read_end(reader);This one is only checked to compile, not run.
Whether the pixels pixel_read_begin asked for have arrived.
Waits for the read to finish and returns the pixels as a Bitmap; free it with deinit.
How a pixel is stored. Plain colours (RGBA8), floating point formats, integer formats, block
compressed formats (BC*, ETC_*) and depth formats.
assert(get_image_bytes_per_texel(.RGBA8) == 4);
assert(get_image_bytes_per_texel(.R8) == 1);↗Pixels in memory, before or after they are on the graphics card. stride is the bytes between rows.
bitmap_alloc makes one, bitmap_load reads one from a file, and deinit frees it.
bitmap: Bitmap;
bitmap_alloc(*bitmap, 4, 2, .RGBA8);
defer deinit(*bitmap);
assert(bitmap.stride == 16 && bitmap.data.count == 32);↗A font file read into memory with FreeType. load_font makes these for you.
Where the origin of a render target is. RIGHT_HANDED puts it at the bottom left with y up;
LEFT_HANDED at the top left with y down.
Extra properties of a texture, such as sRGB and Render_Target.
How a texture is sampled when drawn larger or smaller than its size: LINEAR blends, NEAREST picks one texel.
texture: Texture;
texture_load_from_file(*texture, "sprite.png");
texture_set_filter(*texture, .NEAREST); // crisp pixels↗This one is only checked to compile, not run.
An image on the graphics card. Load one with texture_load_from_file or texture_load_from_memory,
draw it after set_shader_for_images, and release it with texture_destroy.
What Simp knows about a window it draws into: its size in window units, the pixel_scale (device pixels
per unit) and the sample count.
A shader program. set_shader_for_color and set_shader_for_images select the built-in ones.
One corner in the batch that immediate_vertex fills.
The batch of corners waiting to be drawn, with the current window, shader and coordinate system.
Flags that change how text is laid out: small caps, lining figures, no kerning, left justification.
effects: Font_Effects = .SMALLCAPS | .NO_KERNING;
assert((effects & .NO_KERNING) != 0);↗One glyph of a font: its code point, where it sits in the glyph atlas, and its size and advance.
Per-context Simp settings, read as context.simp. text_color is multiplied into the colour of text
being prepared; white leaves it alone.
Font_Quad as text is prepared. draw_prepared_text multiplies it into the colour it is
given, so white (the default) leaves that colour alone.One glyph of prepared text: where it goes, the part of the glyph atlas it shows and its tint.
end_prepare_text fills Dynamic_Font.current_quads with one per glyph, with the pen at the origin.
A font at one size, ready to draw with. load_font returns one; it makes glyphs as text needs them
and keeps them in an atlas. character_height is in device pixels, pixel_scale the number of those
per drawing unit.
pixel_scaleA pending read of a render target's pixels back to the CPU. See pixel_read_begin.