The Simple Abstract Graphics Environment (SAGE) is a minimal software rendering framework designed for educational purposes. The goal of SAGE is to provide a straightforward API for drawing pixels onto a screen.
SAGE is provided as a C library with raylib and web backend implementations, a Sunder library binding to the C implementations, and a JavaScript library for native web development.
/* examples/readme.c */
#include <sage.h>
#define SCREEN_W 640
#define SCREEN_H 480
static struct sage_pixel framebuffer_pixels[SCREEN_W * SCREEN_H] = {0};
static struct sage_image framebuffer = {SCREEN_W, SCREEN_H, framebuffer_pixels};
void
tick(void)
{
// Clear the framebuffer.
sage_fill(framebuffer, SAGE_BLACK);
// Write a sparse swirl of dots into the framebuffer.
for (int y = 0; y < SCREEN_H; ++y) {
for (int x = 0; x < SCREEN_W; ++x) {
int hash = (x * 73 + y * 151 + x * y * 37) % 65536;
if (hash % 777 < 11) {
uint8_t r = ((double)x / (double)SCREEN_W) * 0xFF;
uint8_t b = ((double)y / (double)SCREEN_H) * 0xFF;
struct sage_pixel color = SAGE_RGB(r, 0x00, b);
sage_set_pixel(framebuffer, x, y, color);
}
}
}
// Draw the framebuffer onto the screen.
sage_present();
}
int
main(void)
{
// Platform-specific initialization.
sage_init(framebuffer);
// Repeatedly run `tick` until a platform-specific signal to quit the
// application is received.
sage_run(tick);
// Platform-specific finalization.
sage_fini();
}
<!-- examples/readme.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SAGE Application</title>
<link rel="stylesheet" type="text/css" href="../sage.css">
</head>
<body>
<script src="../sage.js"></script>
<canvas id="main" width="640" height="480"></canvas>
<script type="text/javascript">
const canvas = new SAGE.Canvas("#main");
const tick = () => {
// Clear the framebuffer.
canvas.fill(SAGE.BLACK);
// Write a sparse swirl of dots into the framebuffer.
for (let y = 0; y < canvas.h; ++y) {
for (let x = 0; x < canvas.w; ++x) {
const hash = (x * 73 + y * 151 + x * y * 37) % 65536;
if (hash % 777 < 11) {
const r = Math.floor((x / canvas.w) * 0xFF);
const b = Math.floor((y / canvas.h) * 0xFF);
const color = SAGE.rgb(r, 0x00, b);
canvas.setPixel(x, y, color);
}
}
}
// Draw the framebuffer onto the screen.
canvas.present();
}
canvas.run(tick);
</script>
</body>
</html>
Building and running SAGE applications requires the following dependencies:
- C11 compiler (gcc or clang)
- sunder
- raylib installed via raylib-sunder (raylib backend)
- emsdk (web backend)
You can install these dependencies individually, or if you just want to skip all of that and start writing code, you can run:
# Download and install dependencies locally (run once)
sh setup-local-environment.sh
# Set up environment for SAGE development (run each session)
. ./env
Build a SAGE application from a C or Sunder source file by running the
sage-build
tool as sage-build <backend> <source-file>
:
# Native build using the raylib backend
./sage-build raylib examples/readme.c # outputs examples/readme.c.raylib.out
./sage-build raylib examples/readme.sunder # outputs examples/readme.sunder.raylib.out
# WebAssembly build using the web backend
./sage-build web examples/readme.c # outputs examples/readme.c.web.html
./sage-build web examples/readme.sunder # outputs examples/readme.sunder.web.html
All content in this repository, unless otherwise noted, is licensed under the Zero-Clause BSD license.
See LICENSE for more information.