floooh/sokol

GitHub: floooh/sokol

一组极简的单头文件 C 库,提供跨平台的图形渲染、窗口管理、音频、时间等基础功能,支持桌面、移动端和 WebAssembly。

Stars: 9642 | Forks: 616



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

# Sokol [**查看新动态**](https://github.com/floooh/sokol/blob/master/CHANGELOG.md) (**2026年2月20日**: sokol-app ios+macos+metal: 用 CAMetalLayer+CADisplayLink 替换 MTKView) [![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://static.pigsec.cn/wp-content/uploads/repos/2026/03/99ae406645195543.svg)](https://github.com/floooh/sokol-zig/actions/workflows/main.yml) [![build](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/a3e5747da1195544.svg)](https://github.com/floooh/sokol-nim/actions/workflows/main.yml) [![Odin](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/27d9be6d28195546.svg)](https://github.com/floooh/sokol-odin/actions/workflows/main.yml)[![Rust](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/e357a1c04b195547.svg)](https://github.com/floooh/sokol-rust/actions/workflows/main.yml)[![Dlang](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/479637ef4b195549.svg)](https://github.com/floooh/sokol-d/actions/workflows/build.yml)[![C3](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/67fbe087b2195550.svg)](https://github.com/floooh/sokol-c3/actions/workflows/build.yml) ## 示例与相关项目 - 通过 WASM 查看[在线示例](https://floooh.github.io/sokol-html5/index.html) ([源码](https://github.com/floooh/sokol-samples)) - [Doom Shareware](https://floooh.github.io/doom-sokol/) 移植到 Sokol headers ([源码](https://github.com/floooh/doom-sokol)) - Aras Pranckevičius 创作的 [Everybody Wants to Crank the World](https://aras-p.github.io/demo-pd-cranktheworld/) demo,通过 sokol 移植到 PC/Web ([源码](https://github.com/aras-p/demo-pd-cranktheworld)). - [sokol_gp.h](https://github.com/edubart/sokol_gp) 一个基于 sokol_gfx.h 的 2D 形状绘制库 - [Dear ImGui starterkit](https://github.com/floooh/cimgui-sokol-starterkit) 一个用于编写 C 语言 Dear ImGui 应用的独立入门套件。 - [qoiview](https://github.com/floooh/qoiview) 一个用于查看新型 QOI 图像文件格式的基础查看器 - [Tiny 8-bit 模拟器](https://floooh.github.io/tiny8bit/) - 一个“单文件”的 [C99 吃豆人克隆](https://github.com/floooh/pacman.c/),也提供 [Zig](https://github.com/floooh/pacman.zig/) 版本 - [Soluna](https://github.com/cloudwu/soluna),一个由 @cloudwu 开发的用于制作 2D 游戏的 Lua 框架 - [Deep Future](https://github.com/cloudwu/deepfuture):...以及一个使用 Soluna 实现的游戏 - [Solar Storm](https://store.steampowered.com/app/2754920/Solar_Storm/),一款使用 Odin 和 Sokol 构建的回合制科幻炮战游戏,已在 Steam 上发布。 - [Spanking Runners (Samogonki)](https://store.steampowered.com/app/2599800/Spanking_Runners/),在一个明亮且不寻常的世界中进行街机赛车,已在 Steam 上发布。 - [MEG-4](https://bztsrc.gitlab.io/meg4) 一个用 C89 编写的虚拟幻想主机模拟器,已移植到 sokol - 一个[迷你高尔夫游戏](https://mgerdes.github.io/minigolf.html)([源码](https://github.com/mgerdes/minigolf))。 - [hIghQube](https://github.com/RuiVarela/hIghQube) 一个大量使用 sokol 渲染的游戏 demo - [Senos](https://github.com/RuiVarela/Senos) 一个使用 sokol 作为后端的音乐应用 - ['Dealer's Dungeon'](https://dealers-dungeon.com/demo/)([低画质模式](https://dealers-dungeon.com/demo/?q=3), [源码](https://github.com/bqqbarbhg/spear)) - [移植到 sokol-gfx 的 LearnOpenGL 示例 (可能已过时)](https://zeromake.github.io/learnopengl-examples/)([git 仓库](https://github.com/zeromake/learnopengl-examples)) - [命令行工具](https://github.com/floooh/sokol-tools)(shader 编译器) - [如何在没有构建系统的情况下构建](https://github.com/floooh/sokol-samples#how-to-build-without-a-build-system): 关于如何使用你喜欢的 C/C++ 构建系统将 Sokol headers 集成到你自己的项目中的有用细节 ## 核心库 - [**sokol\_gfx.h**](https://github.com/floooh/sokol/blob/master/sokol_gfx.h): 3D-API 封装 (GL/GLES3/WebGL2 + Metal + D3D11 + WebGPU) - [**sokol\_app.h**](https://github.com/floooh/sokol/blob/master/sokol_app.h): 应用框架封装 (入口 + 窗口 + 3D上下文 + 输入) - [**sokol\_time.h**](https://github.com/floooh/sokol/blob/master/sokol_time.h): 时间测量 - [**sokol\_audio.h**](https://github.com/floooh/sokol/blob/master/sokol_audio.h): 最小化的缓冲流式音频播放 - [**sokol\_fetch.h**](https://github.com/floooh/sokol/blob/master/sokol_fetch.h): 来自 HTTP 和本地文件系统的异步数据流 - [**sokol\_args.h**](https://github.com/floooh/sokol/blob/master/sokol_args.h): 用于 Web 和原生应用的统一命令行/URL 参数解析器 - [**sokol\_log.h**](https://github.com/floooh/sokol/blob/master/sokol_log.h): 为其他 sokol headers 提供标准的日志回调 ## 实用库 - [**sokol\_imgui.h**](https://github.com/floooh/sokol/blob/master/util/sokol_imgui.h): [Dear ImGui](https://github.com/ocornut/imgui) 的 sokol_gfx.h 渲染后端 - [**sokol\_nuklear.h**](https://github.com/floooh/sokol/blob/master/util/sokol_nuklear.h): [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) 的 sokol_gfx.h 渲染后端 - [**sokol\_gl.h**](https://github.com/floooh/sokol/blob/master/util/sokol_gl.h): 基于 sokol_gfx.h 的 OpenGL 1.x 风格立即模式渲染 API - [**sokol\_fontstash.h**](https://github.com/floooh/sokol/blob/master/util/sokol_fontstash.h): [fontstash](https://github.com/memononen/fontstash) 的 sokol_gl.h 渲染后端 - [**sokol\_gfx\_imgui.h**](https://github.com/floooh/sokol/blob/master/util/sokol_gfx_imgui.h): sokol_gfx.h 的调试检查 UI (使用 Dear ImGui 实现) - [**sokol\_debugtext.h**](https://github.com/floooh/sokol/blob/master/util/sokol_debugtext.h): 一个使用复古家用电脑字体的简单文本渲染器 - [**sokol\_memtrack.h**](https://github.com/floooh/sokol/blob/master/util/sokol_memtrack.h): 轻松跟踪 sokol headers 中的内存分配 - [**sokol\_shape.h**](https://github.com/floooh/sokol/blob/master/util/sokol_shape.h): 生成简单形状并将其插入 sokol-gfx 资源创建结构体 - [**sokol\_color.h**](https://github.com/floooh/sokol/blob/master/util/sokol_color.h): X11 风格的颜色常量和用于创建 sg_color 对象的函数 - [**sokol\_spine.h**](https://github.com/floooh/sokol/blob/master/util/sokol_spine.h): Spine C 运行时 的 sokol 风格封装 (http://en.esotericsoftware.com/spine-in-depth) ## ‘官方’语言绑定 这些会在 C headers 更改时自动更新: - [sokol-zig](https://github.com/floooh/sokol-zig) - [sokol-odin](https://github.com/floooh/sokol-odin) - [sokol-nim](https://github.com/floooh/sokol-nim) - [sokol-rust](https://github.com/floooh/sokol-rust) - [sokol-d](https://github.com/floooh/sokol-d) - [sokol-jai](https://github.com/colinbellino/sokol-jai) - [sokol-c3](https://github.com/floooh/sokol-c3) ## 说明 WebAssembly 是‘一等公民’,Sokol headers 的一个重要动机是提供一组跨平台 API,在 Web 平台上占用空间最小,但仍然有用。 核心 headers 是独立的,可以彼此独立使用。 ### 为什么是 C: - 更容易与其他语言集成 - 更容易集成到其他项目中 - 仅给可执行文件增加最小的体积开销 一篇包含更多背景信息的博客文章:[sokol_gfx.h 巡礼](http://floooh.github.io/2017/07/29/sokol-gfx-tour.html) # sokol_gfx.h: - 简单、现代的 GLES3/WebGL2, GL3.3, D3D11, Metal 和 WebGPU 封装 - buffers, images, shaders, pipeline-state-objects 和 render-passes - *不*处理窗口创建或 3D API 上下文初始化 - *不*提供 shader 方言交叉翻译 (**但是**现在有一个‘官方’的 shader 交叉编译器解决方案,可以与 sokol_gfx.h 和 IDE 无缝集成:[详见此处](https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md) # sokol_app.h 一个最小的跨平台应用封装库: - 统一的应用入口 - 用于 3D 渲染的单窗口或画布 - 3D 上下文初始化 - 基于事件的键盘、鼠标和触摸输入 - 支持的平台:Win32, MacOS, Linux (X11), iOS, WASM, Android, UWP - 支持的 3D-API:GL3.3 (GLX/WGL), Metal, D3D11, GLES3/WebGL2 使用 sokol_gfx.h, sokol_app.h 和 sokol-shdc shader 编译器 (未显示 shader 代码) 的原生 Hello-Triangle: ``` #include "sokol_app.h" #include "sokol_gfx.h" #include "sokol_log.h" #include "sokol_glue.h" #include "triangle-sapp.glsl.h" static struct { sg_pipeline pip; sg_bindings bind; sg_pass_action pass_action; } state; static void init(void) { sg_setup(&(sg_desc){ .environment = sglue_environment(), .logger.func = slog_func, }); float vertices[] = { 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 }; state.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(vertices), }); state.pip = sg_make_pipeline(&(sg_pipeline_desc){ .shader = sg_make_shader(triangle_shader_desc(sg_query_backend())), .layout = { .attrs = { [ATTR_triangle_position].format = SG_VERTEXFORMAT_FLOAT3, [ATTR_triangle_color0].format = SG_VERTEXFORMAT_FLOAT4 } }, }); state.pass_action = (sg_pass_action) { .colors[0] = { .load_action=SG_LOADACTION_CLEAR, .clear_value={0.0f, 0.0f, 0.0f, 1.0f } } }; } void frame(void) { sg_begin_pass(&(sg_pass){ .action = state.pass_action, .swapchain = sglue_swapchain() }); sg_apply_pipeline(state.pip); sg_apply_bindings(&state.bind); sg_draw(0, 3, 1); sg_end_pass(); sg_commit(); } void cleanup(void) { sg_shutdown(); } sapp_desc sokol_main(int argc, char* argv[]) { (void)argc; (void)argv; return (sapp_desc){ .init_cb = init, .frame_cb = frame, .cleanup_cb = cleanup, .width = 640, .height = 480, .window_title = "Triangle", .icon.sokol_default = true, .logger.func = slog_func, }; } ``` # sokol_audio.h 一个最小的音频流 API: - 你提供一个 32-bit 浮点样本的单声道或立体声流,sokol_audio.h 将其转发到特定平台的后端 - 两种提供数据的方式: 1. 直接从运行在音频线程中的回调函数填充后端音频缓冲区 2. 或者从你的主循环推送小的音频数据包, 或者由你创建的单独线程 - 平台后端: - Windows: WASAPI - macOS/iOS: CoreAudio - Linux: ALSA - emscripten: WebAudio + ScriptProcessorNode (不使用 emscripten 提供的 OpenAL 或 SDL Audio 封装) 一个使用回调模型的简单单声道方波发生器: ``` // 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; ``` 使用推送模型的相同代码 ``` #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 加载整个文件,或通过 HTTP (emscripten/wasm) 或本地文件系统 (所有原生平台) 异步流式传输数据。 加载文件到静态缓冲区的简单 C99 示例: ``` #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: 简单的跨平台时间测量: ``` #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 用于 Web 和原生应用的统一参数解析。在原生平台上使用 argc/argv,在 Web 上使用 URL 查询字符串。 带有一个参数的示例 URL: https://floooh.github.io/tiny8bit/kc85.html?type=kc85_4 作为命令行应用的相同功能: 像这样解析: ``` #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; } ``` 有关更完整的文档,请参阅 sokol_args.h header,以及 [Tiny Emulators](https://floooh.github.io/tiny8bit/) 以获取更多有趣的使用示例。
标签:3D图形API, AI工具, C/C++库, Direct3D, DLang绑定, GitHub热门, LangChain, Metal, Nim绑定, Odin绑定, OpenGL, Rust绑定, Sokol, STB风格, Vulkan, WASM, WebAssembly, Zig绑定, 低依赖, 单头文件库, 可视化界面, 图形渲染, 多媒体, 客户端加密, 客户端加密, 嵌入式开发, 开源库, 搜索引擎爬虫, 文件格式解析, 游戏开发, 窗口管理, 轻量级, 音频处理