{"id":13424544,"url":"https://github.com/floooh/sokol","last_synced_at":"2025-05-14T07:05:05.794Z","repository":{"id":37796164,"uuid":"97212490","full_name":"floooh/sokol","owner":"floooh","description":"minimal cross-platform standalone C headers","archived":false,"fork":false,"pushed_at":"2025-05-05T12:55:28.000Z","size":13812,"stargazers_count":8178,"open_issues_count":150,"forks_count":557,"subscribers_count":125,"default_branch":"master","last_synced_at":"2025-05-07T06:38:32.622Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://floooh.github.io/sokol-html5","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"zlib","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/floooh.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-07-14T08:38:25.000Z","updated_at":"2025-05-07T05:34:53.000Z","dependencies_parsed_at":"2023-02-15T18:46:05.999Z","dependency_job_id":"5a022d50-5224-4e4a-b9a9-d059935d2f2d","html_url":"https://github.com/floooh/sokol","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floooh%2Fsokol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floooh%2Fsokol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floooh%2Fsokol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floooh%2Fsokol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/floooh","download_url":"https://codeload.github.com/floooh/sokol/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254092648,"owners_count":22013290,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T00:00:56.000Z","updated_at":"2025-05-14T07:05:05.752Z","avatar_url":"https://github.com/floooh.png","language":"C","readme":"\u003cp align=\"center\"\u003e\n    \u003cimg src=\"assets/logo_full_large.png\" style=\"width: 60%\" /\u003e\u003cbr/\u003e\u003cbr/\u003eSimple\n    \u003ca href=\"https://github.com/nothings/stb/blob/master/docs/stb_howto.txt\"\u003eSTB-style\u003c/a\u003e\n    cross-platform libraries for C and C++, written in C.\u003cbr/\u003e\u003cbr/\u003e\n\u003c/p\u003e\n\n# Sokol\n\n[**See what's new**](https://github.com/floooh/sokol/blob/master/CHANGELOG.md) (**15-Mar-2025** sokol_gfx.h: new vertex formats and related behaviour cleanup)\n\n[![Build](/../../actions/workflows/main.yml/badge.svg)](/../../actions/workflows/main.yml) [![Bindings](/../../actions/workflows/gen_bindings.yml/badge.svg)](/../../actions/workflows/gen_bindings.yml) [![build](https://github.com/floooh/sokol-zig/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-zig/actions/workflows/main.yml) [![build](https://github.com/floooh/sokol-nim/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-nim/actions/workflows/main.yml) [![Odin](https://github.com/floooh/sokol-odin/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-odin/actions/workflows/main.yml)[![Rust](https://github.com/floooh/sokol-rust/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-rust/actions/workflows/main.yml)[![Dlang](https://github.com/kassane/sokol-d/actions/workflows/build.yml/badge.svg)](https://github.com/kassane/sokol-d/actions/workflows/build.yml)[![C3](https://github.com/floooh/sokol-c3/actions/workflows/build.yml/badge.svg)](https://github.com/floooh/sokol-c3/actions/workflows/build.yml)\n\n## Examples and Related Projects\n\n- [Live Samples](https://floooh.github.io/sokol-html5/index.html) via WASM ([source](https://github.com/floooh/sokol-samples))\n\n- [Doom Shareware](https://floooh.github.io/doom-sokol/) ported to the Sokol headers ([source](https://github.com/floooh/doom-sokol))\n\n- [Everybody Wants to Crank the World](https://aras-p.github.io/demo-pd-cranktheworld/) demo by\nAras Pranckevičius, PC/web port via sokol ([source](https://github.com/aras-p/demo-pd-cranktheworld)).\n\n- [sokol_gp.h](https://github.com/edubart/sokol_gp) a 2D shape drawing library on top of sokol_gfx.h\n\n- [LearnOpenGL examples ported to sokol-gfx](https://zeromake.github.io/learnopengl-examples/) ([git repo](https://github.com/zeromake/learnopengl-examples))\n\n- [Dear ImGui starterkit](https://github.com/floooh/cimgui-sokol-starterkit) a self-contained starterkit for writing Dear ImGui apps in C.\n\n- [qoiview](https://github.com/floooh/qoiview) a basic viewer for the new QOI image file format\n\n- [Tiny 8-bit emulators](https://floooh.github.io/tiny8bit/)\n\n- A 'single-file' [Pacman clone in C99](https://github.com/floooh/pacman.c/), also available in [Zig](https://github.com/floooh/pacman.zig/)\n\n- [Solar Storm](https://store.steampowered.com/app/2754920/Solar_Storm/), a turn-based scifi artillery game built with Odin and Sokol, released on Steam.\n\n- [Spanking Runners (Samogonki)](https://store.steampowered.com/app/2599800/Spanking_Runners/), arcade racing in a bright and unusual world, released on Steam.\n\n- [MEG-4](https://bztsrc.gitlab.io/meg4) a virtual fantasy console emulator in C89, ported to sokol\n\n- A [Minigolf game](https://mgerdes.github.io/minigolf.html) ([source](https://github.com/mgerdes/minigolf)).\n\n- [hIghQube](https://github.com/RuiVarela/hIghQube) A game demo that used sokol rendering extensively\n\n- [Senos](https://github.com/RuiVarela/Senos) A music app that uses sokol as backend\n\n- ['Dealer's Dungeon'](https://dealers-dungeon.com/demo/) ([lower graphics quality](https://dealers-dungeon.com/demo/?q=3),\n[source](https://github.com/bqqbarbhg/spear))\n\n- [Command line tools](https://github.com/floooh/sokol-tools) (shader compiler)\n\n- [How to build without a build system](https://github.com/floooh/sokol-samples#how-to-build-without-a-build-system):\nuseful details for integrating the Sokol headers into your own project with your favourite C/C++ build system\n\n## Core libraries\n\n- [**sokol\\_gfx.h**](https://github.com/floooh/sokol/blob/master/sokol_gfx.h): 3D-API wrapper (GL/GLES3/WebGL2 + Metal + D3D11 + WebGPU)\n- [**sokol\\_app.h**](https://github.com/floooh/sokol/blob/master/sokol_app.h): app framework wrapper (entry + window + 3D-context + input)\n- [**sokol\\_time.h**](https://github.com/floooh/sokol/blob/master/sokol_time.h): time measurement\n- [**sokol\\_audio.h**](https://github.com/floooh/sokol/blob/master/sokol_audio.h): minimal buffer-streaming audio playback\n- [**sokol\\_fetch.h**](https://github.com/floooh/sokol/blob/master/sokol_fetch.h): asynchronous data streaming from HTTP and local filesystem\n- [**sokol\\_args.h**](https://github.com/floooh/sokol/blob/master/sokol_args.h): unified cmdline/URL arg parser for web and native apps\n- [**sokol\\_log.h**](https://github.com/floooh/sokol/blob/master/sokol_log.h): provides a standard logging callback for the other sokol headers\n\n## Utility libraries\n\n- [**sokol\\_imgui.h**](https://github.com/floooh/sokol/blob/master/util/sokol_imgui.h): sokol_gfx.h rendering backend for [Dear ImGui](https://github.com/ocornut/imgui)\n- [**sokol\\_nuklear.h**](https://github.com/floooh/sokol/blob/master/util/sokol_nuklear.h): sokol_gfx.h rendering backend for [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear)\n- [**sokol\\_gl.h**](https://github.com/floooh/sokol/blob/master/util/sokol_gl.h): OpenGL 1.x style immediate-mode rendering API on top of sokol_gfx.h\n- [**sokol\\_fontstash.h**](https://github.com/floooh/sokol/blob/master/util/sokol_fontstash.h): sokol_gl.h rendering backend for [fontstash](https://github.com/memononen/fontstash)\n- [**sokol\\_gfx\\_imgui.h**](https://github.com/floooh/sokol/blob/master/util/sokol_gfx_imgui.h): debug-inspection UI for sokol_gfx.h (implemented with Dear ImGui)\n- [**sokol\\_debugtext.h**](https://github.com/floooh/sokol/blob/master/util/sokol_debugtext.h): a simple text renderer using vintage home computer fonts\n- [**sokol\\_memtrack.h**](https://github.com/floooh/sokol/blob/master/util/sokol_memtrack.h): easily track memory allocations in sokol headers\n- [**sokol\\_shape.h**](https://github.com/floooh/sokol/blob/master/util/sokol_shape.h): generate simple shapes and plug them into sokol-gfx resource creation structs\n- [**sokol\\_color.h**](https://github.com/floooh/sokol/blob/master/util/sokol_color.h): X11 style color constants and functions for creating sg_color objects\n- [**sokol\\_spine.h**](https://github.com/floooh/sokol/blob/master/util/sokol_spine.h): a sokol-style wrapper around the Spine C runtime (http://en.esotericsoftware.com/spine-in-depth)\n\n## 'Official' Language Bindings\n\nThese are automatically updated on changes to the C headers:\n\n- [sokol-zig](https://github.com/floooh/sokol-zig)\n- [sokol-odin](https://github.com/floooh/sokol-odin)\n- [sokol-nim](https://github.com/floooh/sokol-nim)\n- [sokol-rust](https://github.com/floooh/sokol-rust)\n- [sokol-d](https://github.com/kassane/sokol-d)\n- [sokol-jai](https://github.com/colinbellino/sokol-jai)\n- [sokol-c3](https://github.com/floooh/sokol-c3)\n\n## Notes\n\nWebAssembly is a 'first-class citizen', one important motivation for the\nSokol headers is to provide a collection of cross-platform APIs with a\nminimal footprint on the web platform while still being useful.\n\nThe core headers are standalone and can be used independently from each other.\n\n### Why C:\n\n- easier integration with other languages\n- easier integration into other projects\n- adds only minimal size overhead to executables\n\nA blog post with more background info: [A Tour of sokol_gfx.h](http://floooh.github.io/2017/07/29/sokol-gfx-tour.html)\n\n# sokol_gfx.h:\n\n- simple, modern wrapper around GLES3/WebGL2, GL3.3, D3D11, Metal, and WebGPU\n- buffers, images, shaders, pipeline-state-objects and render-passes\n- does *not* handle window creation or 3D API context initialization\n- does *not* provide shader dialect cross-translation (**BUT** there's now an 'official' shader-cross-compiler solution which\nseamlessly integrates with sokol_gfx.h and IDEs: [see here for details](https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md)\n\n# sokol_app.h\n\nA minimal cross-platform application-wrapper library:\n\n- unified application entry\n- single window or canvas for 3D rendering\n- 3D context initialization\n- event-based keyboard, mouse and touch input\n- supported platforms: Win32, MacOS, Linux (X11), iOS, WASM, Android, UWP\n- supported 3D-APIs: GL3.3 (GLX/WGL), Metal, D3D11, GLES3/WebGL2\n\nThe vanilla Hello-Triangle using sokol_gfx.h, sokol_app.h and the\nsokol-shdc shader compiler (shader code not shown):\n\n```c\n#include \"sokol_app.h\"\n#include \"sokol_gfx.h\"\n#include \"sokol_log.h\"\n#include \"sokol_glue.h\"\n#include \"triangle-sapp.glsl.h\"\n\nstatic struct {\n    sg_pipeline pip;\n    sg_bindings bind;\n    sg_pass_action pass_action;\n} state;\n\nstatic void init(void) {\n    sg_setup(\u0026(sg_desc){\n        .environment = sglue_environment(),\n        .logger.func = slog_func,\n    });\n\n    float vertices[] = {\n         0.0f,  0.5f, 0.5f,     1.0f, 0.0f, 0.0f, 1.0f,\n         0.5f, -0.5f, 0.5f,     0.0f, 1.0f, 0.0f, 1.0f,\n        -0.5f, -0.5f, 0.5f,     0.0f, 0.0f, 1.0f, 1.0f\n    };\n    state.bind.vertex_buffers[0] = sg_make_buffer(\u0026(sg_buffer_desc){\n        .data = SG_RANGE(vertices),\n    });\n\n    state.pip = sg_make_pipeline(\u0026(sg_pipeline_desc){\n        .shader = sg_make_shader(triangle_shader_desc(sg_query_backend())),\n        .layout = {\n            .attrs = {\n                [ATTR_triangle_position].format = SG_VERTEXFORMAT_FLOAT3,\n                [ATTR_triangle_color0].format = SG_VERTEXFORMAT_FLOAT4\n            }\n        },\n    });\n\n    state.pass_action = (sg_pass_action) {\n        .colors[0] = { .load_action=SG_LOADACTION_CLEAR, .clear_value={0.0f, 0.0f, 0.0f, 1.0f } }\n    };\n}\n\nvoid frame(void) {\n    sg_begin_pass(\u0026(sg_pass){ .action = state.pass_action, .swapchain = sglue_swapchain() });\n    sg_apply_pipeline(state.pip);\n    sg_apply_bindings(\u0026state.bind);\n    sg_draw(0, 3, 1);\n    sg_end_pass();\n    sg_commit();\n}\n\nvoid cleanup(void) {\n    sg_shutdown();\n}\n\nsapp_desc sokol_main(int argc, char* argv[]) {\n    (void)argc; (void)argv;\n    return (sapp_desc){\n        .init_cb = init,\n        .frame_cb = frame,\n        .cleanup_cb = cleanup,\n        .width = 640,\n        .height = 480,\n        .window_title = \"Triangle\",\n        .icon.sokol_default = true,\n        .logger.func = slog_func,\n    };\n}\n```\n\n# sokol_audio.h\n\nA minimal audio-streaming API:\n\n- you provide a mono- or stereo-stream of 32-bit float samples which sokol_audio.h forwards into platform-specific backends\n- two ways to provide the data:\n    1. directly fill backend audio buffer from your callback function running in the audio thread\n    2. alternatively push small packets of audio data from your main loop,\n    or a separate thread created by you\n- platform backends:\n    - Windows: WASAPI\n    - macOS/iOS: CoreAudio\n    - Linux: ALSA\n    - emscripten: WebAudio + ScriptProcessorNode (doesn't use the emscripten-provided OpenAL or SDL Audio wrappers)\n\nA simple mono square-wave generator using the callback model:\n\n```c\n// the sample callback, running in audio thread\nstatic void stream_cb(float* buffer, int num_frames, int num_channels) {\n    assert(1 == num_channels);\n    static uint32_t count = 0;\n    for (int i = 0; i \u003c num_frames; i++) {\n        buffer[i] = (count++ \u0026 (1\u003c\u003c3)) ? 0.5f : -0.5f;\n    }\n}\n\nint main() {\n    // init sokol-audio with default params\n    saudio_setup(\u0026(saudio_desc){\n        .stream_cb = stream_cb,\n        .logger.func = slog_func,\n    });\n\n    // run main loop\n    ...\n\n    // shutdown sokol-audio\n    saudio_shutdown();\n    return 0;\n```\n\nThe same code using the push-model\n\n```c\n#define BUF_SIZE (32)\nint main() {\n    // init sokol-audio with default params, no callback\n    saudio_setup(\u0026(saudio_desc){\n        .logger.func = slog_func,\n    });\n    assert(saudio_channels() == 1);\n\n    // a small intermediate buffer so we don't need to push\n    // individual samples, which would be quite inefficient\n    float buf[BUF_SIZE];\n    int buf_pos = 0;\n    uint32_t count = 0;\n\n    // push samples from main loop\n    bool done = false;\n    while (!done) {\n        // generate and push audio samples...\n        int num_frames = saudio_expect();\n        for (int i = 0; i \u003c num_frames; i++) {\n            // simple square wave generator\n            buf[buf_pos++] = (count++ \u0026 (1\u003c\u003c3)) ? 0.5f : -0.5f;\n            if (buf_pos == BUF_SIZE) {\n                buf_pos = 0;\n                saudio_push(buf, BUF_SIZE);\n            }\n        }\n        // handle other per-frame stuff...\n        ...\n    }\n\n    // shutdown sokol-audio\n    saudio_shutdown();\n    return 0;\n}\n```\n\n# sokol_fetch.h\n\nLoad entire files, or stream data asynchronously over HTTP (emscripten/wasm)\nor the local filesystem (all native platforms).\n\nSimple C99 example loading a file into a static buffer:\n\n```c\n#include \"sokol_fetch.h\"\n#include \"sokol_log.h\"\n\nstatic void response_callback(const sfetch_response*);\n\n#define MAX_FILE_SIZE (1024*1024)\nstatic uint8_t buffer[MAX_FILE_SIZE];\n\n// application init\nstatic void init(void) {\n    ...\n    // setup sokol-fetch with default config:\n    sfetch_setup(\u0026(sfetch_desc_t){ .logger.func = slog_func });\n\n    // start loading a file into a statically allocated buffer:\n    sfetch_send(\u0026(sfetch_request_t){\n        .path = \"hello_world.txt\",\n        .callback = response_callback\n        .buffer_ptr = buffer,\n        .buffer_size = sizeof(buffer)\n    });\n}\n\n// per frame...\nstatic void frame(void) {\n    ...\n    // need to call sfetch_dowork() once per frame to 'turn the gears':\n    sfetch_dowork();\n    ...\n}\n\n// the response callback is where the interesting stuff happens:\nstatic void response_callback(const sfetch_response_t* response) {\n    if (response-\u003efetched) {\n        // data has been loaded into the provided buffer, do something\n        // with the data...\n        const void* data = response-\u003ebuffer_ptr;\n        uint64_t data_size = response-\u003efetched_size;\n    }\n    // the finished flag is set both on success and failure\n    if (response-\u003efailed) {\n        // oops, something went wrong\n        switch (response-\u003eerror_code) {\n            SFETCH_ERROR_FILE_NOT_FOUND: ...\n            SFETCH_ERROR_BUFFER_TOO_SMALL: ...\n            ...\n        }\n    }\n}\n\n// application shutdown\nstatic void shutdown(void) {\n    ...\n    sfetch_shutdown();\n    ...\n}\n```\n\n# sokol_time.h:\n\nSimple cross-platform time measurement:\n\n```c\n#include \"sokol_time.h\"\n...\n/* initialize sokol_time */\nstm_setup();\n\n/* take start timestamp */\nuint64_t start = stm_now();\n\n...some code to measure...\n\n/* compute elapsed time */\nuint64_t elapsed = stm_since(start);\n\n/* convert to time units */\ndouble seconds = stm_sec(elapsed);\ndouble milliseconds = stm_ms(elapsed);\ndouble microseconds = stm_us(elapsed);\ndouble nanoseconds = stm_ns(elapsed);\n\n/* difference between 2 time stamps */\nuint64_t start = stm_now();\n...\nuint64_t end = stm_now();\nuint64_t elapsed = stm_diff(end, start);\n\n/* compute a 'lap time' (e.g. for fps) */\nuint64_t last_time = 0;\nwhile (!done) {\n    ...render something...\n    double frame_time_ms = stm_ms(stm_laptime(\u0026last_time));\n}\n```\n\n# sokol_args.h\n\nUnified argument parsing for web and native apps. Uses argc/argv on native\nplatforms and the URL query string on the web.\n\nExample URL with one arg:\n\nhttps://floooh.github.io/tiny8bit/kc85.html?type=kc85_4\n\nThe same as command line app:\n\n\u003e kc85 type=kc85_4\n\nParsed like this:\n\n```c\n#include \"sokol_args.h\"\n\nint main(int argc, char* argv[]) {\n    sargs_setup(\u0026(sargs_desc){ .argc=argc, .argv=argv });\n    if (sargs_exists(\"type\")) {\n        if (sargs_equals(\"type\", \"kc85_4\")) {\n            // start as KC85/4\n        }\n        else if (sargs_equals(\"type\", \"kc85_3\")) {\n            // start as KC85/3\n        }\n        else {\n            // start as KC85/2\n        }\n    }\n    sargs_shutdown();\n    return 0;\n}\n```\n\nSee the sokol_args.h header for a more complete documentation, and the [Tiny\nEmulators](https://floooh.github.io/tiny8bit/) for more interesting usage examples.\n","funding_links":[],"categories":["Source Code Collections","C","Libraries \u0026 Frameworks:","C/C++程序设计","Geometry, Graphics Processing, and Game Development","Graphics","Libraries"],"sub_categories":["Advanced books","Graphics","资源传输下载","C"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffloooh%2Fsokol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffloooh%2Fsokol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffloooh%2Fsokol/lists"}