• Stars
    star
    5,629
  • Rank 6,883 (Top 0.2 %)
  • Language
    C
  • License
    zlib License
  • Created almost 7 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

minimal cross-platform standalone C headers

Sokol

Simple STB-style cross-platform libraries for C and C++, written in C.

See what's new (19-May-2023 BREAKING CHANGES in sokol_gfx.h around render pass behaviour)

Build Bindings build build OdinRust

Examples and Related Projects

Core libraries

  • sokol_gfx.h: 3D-API wrapper (GL + Metal + D3D11)
  • sokol_app.h: app framework wrapper (entry + window + 3D-context + input)
  • sokol_time.h: time measurement
  • sokol_audio.h: minimal buffer-streaming audio playback
  • sokol_fetch.h: asynchronous data streaming from HTTP and local filesystem
  • sokol_args.h: unified cmdline/URL arg parser for web and native apps
  • sokol_log.h: provides a standard logging callback for the other sokol headers

Utility libraries

'Official' Language Bindings

These are automatically updated on changes to the C headers:

Notes

WebAssembly is a 'first-class citizen', one important motivation for the Sokol headers is to provide a collection of cross-platform APIs with a minimal footprint on the web platform while still being useful.

The core headers are standalone and can be used independently from each other.

Why C:

  • easier integration with other languages
  • easier integration into other projects
  • adds only minimal size overhead to executables

A blog post with more background info: A Tour of sokol_gfx.h

sokol_gfx.h:

  • simple, modern wrapper around GLES3/WebGL2, GL3.3, D3D11 and Metal
  • buffers, images, shaders, pipeline-state-objects and render-passes
  • does not handle window creation or 3D API context initialization
  • does not provide shader dialect cross-translation (BUT there's now an 'official' shader-cross-compiler solution which seamlessly integrates with sokol_gfx.h and IDEs: see here for details

A triangle in C99 with GLFW:

#define SOKOL_IMPL
#define SOKOL_GLCORE33
#include "sokol_gfx.h"
#include "sokol_log.h"
#define GLFW_INCLUDE_NONE
#include "GLFW/glfw3.h"

int main() {

    /* create window and GL context via GLFW */
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    GLFWwindow* w = glfwCreateWindow(640, 480, "Sokol Triangle GLFW", 0, 0);
    glfwMakeContextCurrent(w);
    glfwSwapInterval(1);

    /* setup sokol_gfx */
    sg_setup(&(sg_desc){
        .logger.func = slog_func,
    });

    /* a vertex buffer */
    const float vertices[] = {
        // positions            // colors
         0.0f,  0.5f, 0.5f,     1.0f, 0.0f, 0.0f, 1.0f,
         0.5f, -0.5f, 0.5f,     0.0f, 1.0f, 0.0f, 1.0f,
        -0.5f, -0.5f, 0.5f,     0.0f, 0.0f, 1.0f, 1.0f
    };
    sg_buffer vbuf = sg_make_buffer(&(sg_buffer_desc){
        .data = SG_RANGE(vertices)
    });

    /* a shader */
    sg_shader shd = sg_make_shader(&(sg_shader_desc){
        .vs.source =
            "#version 330\n"
            "layout(location=0) in vec4 position;\n"
            "layout(location=1) in vec4 color0;\n"
            "out vec4 color;\n"
            "void main() {\n"
            "  gl_Position = position;\n"
            "  color = color0;\n"
            "}\n",
        .fs.source =
            "#version 330\n"
            "in vec4 color;\n"
            "out vec4 frag_color;\n"
            "void main() {\n"
            "  frag_color = color;\n"
            "}\n"
    });

    /* a pipeline state object (default render states are fine for triangle) */
    sg_pipeline pip = sg_make_pipeline(&(sg_pipeline_desc){
        .shader = shd,
        .layout = {
            .attrs = {
                [0].format=SG_VERTEXFORMAT_FLOAT3,
                [1].format=SG_VERTEXFORMAT_FLOAT4
            }
        }
    });

    /* resource bindings */
    sg_bindings bind = {
        .vertex_buffers[0] = vbuf
    };

    /* default pass action (clear to grey) */
    sg_pass_action pass_action = {0};

    /* draw loop */
    while (!glfwWindowShouldClose(w)) {
        int cur_width, cur_height;
        glfwGetFramebufferSize(w, &cur_width, &cur_height);
        sg_begin_default_pass(&pass_action, cur_width, cur_height);
        sg_apply_pipeline(pip);
        sg_apply_bindings(&bind);
        sg_draw(0, 3, 1);
        sg_end_pass();
        sg_commit();
        glfwSwapBuffers(w);
        glfwPollEvents();
    }

    /* cleanup */
    sg_shutdown();
    glfwTerminate();
    return 0;
}

sokol_app.h

A minimal cross-platform application-wrapper library:

  • unified application entry
  • single window or canvas for 3D rendering
  • 3D context initialization
  • event-based keyboard, mouse and touch input
  • supported platforms: Win32, MacOS, Linux (X11), iOS, WASM, Android, UWP
  • supported 3D-APIs: GL3.3 (GLX/WGL), Metal, D3D11, GLES3/WebGL2

A simple clear-loop sample using sokol_app.h and sokol_gfx.h (does not include separate sokol.c/.m implementation file which is necessary to split the Objective-C code from the C code of the sample):

#include "sokol_gfx.h"
#include "sokol_app.h"
#include "sokol_log.h"
#include "sokol_glue.h"

sg_pass_action pass_action;

void init(void) {
    sg_setup(&(sg_desc){
        .context = sapp_sgcontext(),
        .logger.func = slog_func,
    });
    pass_action = (sg_pass_action) {
        .colors[0] = { .load_action=SG_LOADACTION_CLEAR, .clear_value={1.0f, 0.0f, 0.0f, 1.0f} }
    };
}

void frame(void) {
    float g = pass_action.colors[0].clear_value.g + 0.01f;
    pass_action.colors[0].clear_value.g = (g > 1.0f) ? 0.0f : g;
    sg_begin_default_pass(&pass_action, sapp_width(), sapp_height());
    sg_end_pass();
    sg_commit();
}

void cleanup(void) {
    sg_shutdown();
}

sapp_desc sokol_main(int argc, char* argv[]) {
    return (sapp_desc){
        .init_cb = init,
        .frame_cb = frame,
        .cleanup_cb = cleanup,
        .width = 400,
        .height = 300,
        .window_title = "Clear Sample",
        .logger.func = slog_func,
    };
}

sokol_audio.h

A minimal audio-streaming API:

  • you provide a mono- or stereo-stream of 32-bit float samples which sokol_audio.h forwards into platform-specific backends
  • two ways to provide the data:
    1. directly fill backend audio buffer from your callback function running in the audio thread
    2. alternatively push small packets of audio data from your main loop, or a separate thread created by you
  • platform backends:
    • Windows: WASAPI
    • macOS/iOS: CoreAudio
    • Linux: ALSA
    • emscripten: WebAudio + ScriptProcessorNode (doesn't use the emscripten-provided OpenAL or SDL Audio wrappers)

A simple mono square-wave generator using the callback model:

// the sample callback, running in audio thread
static void stream_cb(float* buffer, int num_frames, int num_channels) {
    assert(1 == num_channels);
    static uint32_t count = 0;
    for (int i = 0; i < num_frames; i++) {
        buffer[i] = (count++ & (1<<3)) ? 0.5f : -0.5f;
    }
}

int main() {
    // init sokol-audio with default params
    saudio_setup(&(saudio_desc){
        .stream_cb = stream_cb,
        .logger.func = slog_func,
    });

    // run main loop
    ...

    // shutdown sokol-audio
    saudio_shutdown();
    return 0;

The same code using the push-model

#define BUF_SIZE (32)
int main() {
    // init sokol-audio with default params, no callback
    saudio_setup(&(saudio_desc){
        .logger.func = slog_func,
    });
    assert(saudio_channels() == 1);

    // a small intermediate buffer so we don't need to push
    // individual samples, which would be quite inefficient
    float buf[BUF_SIZE];
    int buf_pos = 0;
    uint32_t count = 0;

    // push samples from main loop
    bool done = false;
    while (!done) {
        // generate and push audio samples...
        int num_frames = saudio_expect();
        for (int i = 0; i < num_frames; i++) {
            // simple square wave generator
            buf[buf_pos++] = (count++ & (1<<3)) ? 0.5f : -0.5f;
            if (buf_pos == BUF_SIZE) {
                buf_pos = 0;
                saudio_push(buf, BUF_SIZE);
            }
        }
        // handle other per-frame stuff...
        ...
    }

    // shutdown sokol-audio
    saudio_shutdown();
    return 0;
}

sokol_fetch.h

Load entire files, or stream data asynchronously over HTTP (emscripten/wasm) or the local filesystem (all native platforms).

Simple C99 example loading a file into a static buffer:

#include "sokol_fetch.h"
#include "sokol_log.h"

static void response_callback(const sfetch_response*);

#define MAX_FILE_SIZE (1024*1024)
static uint8_t buffer[MAX_FILE_SIZE];

// application init
static void init(void) {
    ...
    // setup sokol-fetch with default config:
    sfetch_setup(&(sfetch_desc_t){ .logger.func = slog_func });

    // start loading a file into a statically allocated buffer:
    sfetch_send(&(sfetch_request_t){
        .path = "hello_world.txt",
        .callback = response_callback
        .buffer_ptr = buffer,
        .buffer_size = sizeof(buffer)
    });
}

// per frame...
static void frame(void) {
    ...
    // need to call sfetch_dowork() once per frame to 'turn the gears':
    sfetch_dowork();
    ...
}

// the response callback is where the interesting stuff happens:
static void response_callback(const sfetch_response_t* response) {
    if (response->fetched) {
        // data has been loaded into the provided buffer, do something
        // with the data...
        const void* data = response->buffer_ptr;
        uint64_t data_size = response->fetched_size;
    }
    // the finished flag is set both on success and failure
    if (response->failed) {
        // oops, something went wrong
        switch (response->error_code) {
            SFETCH_ERROR_FILE_NOT_FOUND: ...
            SFETCH_ERROR_BUFFER_TOO_SMALL: ...
            ...
        }
    }
}

// application shutdown
static void shutdown(void) {
    ...
    sfetch_shutdown();
    ...
}

sokol_time.h:

Simple cross-platform time measurement:

#include "sokol_time.h"
...
/* initialize sokol_time */
stm_setup();

/* take start timestamp */
uint64_t start = stm_now();

...some code to measure...

/* compute elapsed time */
uint64_t elapsed = stm_since(start);

/* convert to time units */
double seconds = stm_sec(elapsed);
double milliseconds = stm_ms(elapsed);
double microseconds = stm_us(elapsed);
double nanoseconds = stm_ns(elapsed);

/* difference between 2 time stamps */
uint64_t start = stm_now();
...
uint64_t end = stm_now();
uint64_t elapsed = stm_diff(end, start);

/* compute a 'lap time' (e.g. for fps) */
uint64_t last_time = 0;
while (!done) {
    ...render something...
    double frame_time_ms = stm_ms(stm_laptime(&last_time));
}

sokol_args.h

Unified argument parsing for web and native apps. Uses argc/argv on native platforms and the URL query string on the web.

Example URL with one arg:

https://floooh.github.io/tiny8bit/kc85.html?type=kc85_4

The same as command line app:

kc85 type=kc85_4

Parsed like this:

#include "sokol_args.h"

int main(int argc, char* argv[]) {
    sargs_setup(&(sargs_desc){ .argc=argc, .argv=argv });
    if (sargs_exists("type")) {
        if (sargs_equals("type", "kc85_4")) {
            // start as KC85/4
        }
        else if (sargs_equals("type", "kc85_3")) {
            // start as KC85/3
        }
        else {
            // start as KC85/2
        }
    }
    sargs_shutdown();
    return 0;
}

See the sokol_args.h header for a more complete documentation, and the Tiny Emulators for more interesting usage examples.

More Repositories

1

oryol

A small, portable and extensible C++ 3D coding framework
C++
1,965
star
2

chips

8-bit chip and system emulators in standalone C headers
C
890
star
3

sokol-samples

Sample code for https://github.com/floooh/sokol
C
527
star
4

pacman.c

Simple Pacman clone written in C99.
C
464
star
5

fips

High-level build system for distributed, multi-platform C/C++ projects.
Python
457
star
6

chips-test

Tests and sample code for https://github.com/floooh/chips
C
366
star
7

sokol-zig

Zig bindings for the sokol headers (https://github.com/floooh/sokol)
C
264
star
8

v6502r

visual6502 remixed
C
251
star
9

pacman.zig

Simple Pacman clone written in Zig.
Zig
197
star
10

sokol-tools

Command line tools for use with sokol headers
C++
190
star
11

cimgui-sokol-starterkit

A minimal self-contained Dear ImGui starter project for Windows, Linux and macOS.
C++
184
star
12

bookmarks

Links to stuff that looks useful.
139
star
13

qoiview

QOI image viewer on top of the Sokol headers
C
123
star
14

emu-info

Various emulator-related infos from all over the net.
Assembly
105
star
15

yakc

Yet another KC emulator
Assembly
104
star
16

oryol-samples

Oryol extension module samples
C++
81
star
17

rz80

Z80 chip family emulator library written in Rust.
Rust
72
star
18

sokol-nim

nim bindings for https://github.com/floooh/sokol
C
70
star
19

gliml

Minimalistic image loader library for GL projects
C++
62
star
20

fbxc

FBX cruncher (FBX + rules => JSON + vertex data blob)
C++
61
star
21

altai

Modern WebGL wrapper in TypeScript
TypeScript
53
star
22

sokol-odin

Odin bindings for the sokol headers (https://github.com/floooh/sokol)
C
46
star
23

sokol-rust

Rust bindings for the sokol headers (https://github.com/floooh/sokol)
C
44
star
24

kc85.zig

A KC85 emulator written in Zig
Zig
42
star
25

tiny8bit

WebPage for https://github.com/floooh/chips-test
HTML
36
star
26

docker-c64

C64 emulator running in docker
C
31
star
27

sokol-tools-bin

Binaries and fips integration for https://github.com/floooh/sokol-tools
Python
21
star
28

oryol-animation

Oryol animation and skinned-character-rendering modules
C++
19
star
29

oryol-imgui

Dear Imgui wrapper module for Oryol
C++
18
star
30

fips-bgfx

fipsified version of bgfx (https://github.com/bkaradzic/bgfx)
CMake
17
star
31

sokol-webgpu

HTML
15
star
32

floooh.github.io

Move blog and personal web page over to github (work in progress)
HTML
14
star
33

sokol-nim-samples

Example code for https://github.com/floooh/sokol-nim
Nim
13
star
34

vscode-kcide

Retro assembly IDE for VSCode
TypeScript
13
star
35

vscode-emscripten-debugging

Example repository for Emscripten WASM debugging in VSCode
C
11
star
36

visualz80remix

[WIP] WASM for https://github.com/floooh/v6502r with Z80 netlist
HTML
11
star
37

visual6502remix

Webpage for https://github.com/floooh/v6502r
HTML
11
star
38

oryol-tools

Asset exporter tools for Oryol engine
C++
10
star
39

drahtgitter

A toolkit for converting and processing 3d data in python.
Python
9
star
40

virtualkc

Webpage for the YAKC KC85 emulator
HTML
9
star
41

oryol-tbui

Integrate TurbobadgerUI with Oryol
C++
8
star
42

objc-ast-experiments

C
7
star
43

sokol-html5

webpage for https://github.com/floooh/sokol-samples
HTML
7
star
44

fibs

Nothing to see here, move along :)
TypeScript
7
star
45

fips-libcurl

Precompiled, stripped down libcurl libs for Oryol
C
6
star
46

visual2a03remix

webpage for the Ricoh 2A03 simulation
HTML
6
star
47

tiny8bitvs

Experiment to integrate a 'chips' WASM emulator into a VSCode tab.
TypeScript
6
star
48

kc85sdk

Experimental C-SDK for KC85 home computers
Python
6
star
49

fips-soloud

fipsified version of Soloud audio lib (https://github.com/jarikomppa/soloud)
CMake
6
star
50

voxel-test

Place to experiment with stb_voxel_renderer.h and Oryol
C
5
star
51

oryol-nuklear

Integrate Nuklear UI with Oryol engine
C++
5
star
52

oryol-test-app

Oryol testing app in its own repo
C++
5
star
53

fibs-hello-world

Most minimal fibs test project.
TypeScript
5
star
54

oryol-fileformats

Structure definitions for Oryol binary file formats.
C++
4
star
55

headeronly-perf

C
4
star
56

fibs-libs

Collection of fibs project wrappers for common 3rd-party libraries.
TypeScript
4
star
57

sokol-wgpu-preview

Temporary sneak preview website for sokol WebGPU samples.
HTML
4
star
58

emsc-interop-demo

Simple example to demonstrate calling a C function from Javascript.
HTML
4
star
59

easmx

A fork of the asmx assembler usable as embeddable library.
C
4
star
60

oryol-sound

Legacy Oryol sound module (uses OpenAL)
C++
3
star
61

docker-kc85

A KC85/4 emulator in Docker.
C
3
star
62

hcasm

8-bit home computer assembler in Typescript
TypeScript
3
star
63

fips-nuklear

fips build system wrapper for nuklear UI (https://github.com/vurtun/nuklear)
Python
3
star
64

chef-emscripten

Chef cookbook to setup an emscripten build environment.
Ruby
3
star
65

kcide-sample

Sample project for VSCode KC IDE extension
Assembly
3
star
66

oryol-webgl2

Webpage files for bleeding edge WebGL2 Oryol samples.
HTML
3
star
67

fips-hello-world

Test project for fips build system.
Python
3
star
68

fips-bullet

fips wrapper for bullet phyiscs
CMake
2
star
69

fips-spirvcross

fips wrapper for SPIRV-Cross
CMake
2
star
70

flohofwoe.www

JavaScript
2
star
71

fips-glfw

fipsified GLFW (https://github.com/glfw/glfw)
CMake
2
star
72

fips-cjson

fipsified cJSON lib
CMake
2
star
73

fibs-sokol-test

Fibs + sokol + sokol-shdc + stb
C
2
star
74

fips-cpptoml

fipsified cpptoml (https://github.com/skystrife/cpptoml)
2
star
75

fips-vld

Fipsified VLD (Visual Leak Detector)
C
2
star
76

fips-zlib

fipsified zlib
C
2
star
77

nvidia-driver-issue

C
1
star
78

fips-unittestpp

fipsified UnitTest++
C++
1
star
79

chef-cmake

Chef cookbook for installing cmake from source tarball
Ruby
1
star
80

webgl2-test

WebGL2 bug repro tests (wip)
JavaScript
1
star
81

chef-nacl

Chef cookbook to install the Google Native Client SDK
Ruby
1
star
82

fips-remotery

fipsified version of Remotery (https://github.com/Celtoys/Remotery)
CMake
1
star
83

tmp-http-test

TypeScript
1
star
84

fibs-test

Top level test project for https://github.com/floooh/fibs
C
1
star
85

oryol-simple

The most simple Oryol Gfx app
Python
1
star
86

fips-lua

fips wrapper for lua
CMake
1
star
87

fips-glm

Fipsified glm lib (https://github.com/g-truc/glm)
1
star
88

fibs-utils

Common helpers and utilities for fibs projects.
TypeScript
1
star
89

tiny8bit-preview

Temporary preview webpage repo for https://github.com/floooh/chips-test
HTML
1
star