SDL_GPU 最小化、单头文件、高性能的2D图形绘制库

Hacker News Top 工具

摘要

SDL_gp 是一个为 SDL3 设计的最小化、高性能的2D图形绘制库,从 sokol_gp 移植而来,提供了简单的资源管理系统。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/07/30 16:50

n67094/sdl_gp

来源:https://github.com/n67094/sdl_gp

SDL_gp 🏁🏎️

一个基于SDL3的简约高性能2D(图形)绘制器。

这是 sokol_gp (https://github.com/edubart/sokol_gp) 到 SDL3 的移植,主要区别在于:

sokol_gp 依赖 sokol,其内部管理资源;而 SDL_gpu 是更低层的,不管理资源。因此 SDL_gp 提供了一个非常类似于 sokol 的简单资源管理系统。

示例

基本图形:

基本图形截图

矩形:

矩形截图

精灵:

精灵截图

混合模式:

混合模式截图

快速开始

如果你想直接上手,可以查看 samples 文件夹。

下面是一个绘制红色矩形的简单示例:

// 获取当前帧的命令缓冲区
SDL_GPUCommandBuffer *cmd_buffer = SDL_AcquireGPUCommandBuffer(device);

// 开始新帧
SDL_GPBegin(WINDOW_WIDTH, WINDOW_HEIGHT);
{
    // 将屏幕清除为黑色。
    SDL_GPSetColor((SDL_Color){ 0, 0, 0, 255 });
    SDL_GPClear();

    // 绘制一个红色实心矩形。
    SDL_GPSetColor((SDL_Color){ 255, 0, 0, 255 });
    {
        SDL_GPDrawRectFilled((SDL_GPRect){ 10, 10, 100, 100 });
    }

    // 调用者可以渲染到交换链或纹理。这里我们渲染到交换链。
    SDL_GPUTexture *swapchain_texture = NULL;

    SDL_WaitAndAcquireGPUSwapchainTexture(
        cmd_buffer, window, &swapchain_texture, NULL, NULL);

    SDL_GPFlush(cmd_buffer, swapchain_texture);
}
SDL_GPEnd();
SDL_SubmitGPUCommandBuffer(cmd_buffer);

SDL_Delay(DELTA_TIME_MS);

快速参考

错误 API:

// 获取 SDL_gp 中发生的最后一个错误。如果没有发生错误,返回 SDL_GP_ERROR_NONE。
SDL_GP_Error SDL_GPGetLastError(void);

// 获取描述 SDL_GP_Error 值的人类可读字符串。如果错误值无法识别,返回 "Unknown error"。
const char *SDL_GPGetErrorMessage(SDL_GP_Error error);

图像 API:

  // 从 SDL_Surface 创建图像。如果创建失败,返回无效图像,使用 SDL_GPGetLastError() 获取更多错误信息。
  SDL_GPImage SDL_GPCreateImage(SDL_Surface *surface);

  // 销毁图像并释放其资源。
  void SDL_GPDestroyImage(SDL_GPImage image);

  // 获取与图像关联的 GPU 纹理。如果图像无效,返回 NULL。
  SDL_GPUTexture *SDL_GPGetImageGPUTexture(SDL_GPImage image);

  // 获取图像的宽度(像素)。如果图像无效,返回 0。
  int SDL_GPGetImageWidth(SDL_GPImage image);

  // 获取图像的高度(像素)。如果图像无效,返回 0。
  int SDL_GPGetImageHeight(SDL_GPImage image);

着色器 API:

  // 根据顶点和片段着色器描述创建着色器。如果创建失败,返回无效着色器,使用 SDL_GPGetLastError() 获取更多错误信息。
  SDL_GPShader SDL_GPCreateShader(SDL_GPShaderDesc *desc);

  // 获取与 SDL_gp 着色器关联的 SDL 着色器。如果着色器无效,返回 NULL。
  SDL_GPUShader *SDL_GPGetGPUShader(SDL_GPShader shader);

  // 销毁着色器并释放其资源。
  void SDL_GPDestroyShader(SDL_GPShader shader);

管线 API:

  // 创建图形管线。如果创建失败,返回无效管线,使用 SDL_GPGetLastError() 获取更多错误信息。
  SDL_GPPipeline
  SDL_GPCreatePipeline(SDL_GPShader shader_vert,
                       SDL_GPShader shader_frag,
                       SDL_GPPrimitiveType primitive_type,
                       SDL_GPBlendMode blend_mode);

  // 销毁图形管线并释放其资源。
  void SDL_GPDestroyPipeline(SDL_GPPipeline pipeline);

  // 获取与 SDL_gp 管线关联的 GPU 图形管线。如果管线无效,返回 NULL。
  SDL_GPUGraphicsPipeline *SDL_GPGetGPUPipeline(SDL_GPPipeline pipeline);

绘制器 API:

  // 设置 SDL_GP 上下文。如果设置失败返回 false,使用 SDL_GPGetLastError() 获取更多错误信息。
  bool SDL_GPSetup(SDL_GPDesc *desc);

  // 关闭 SDL_GP 上下文。
  void SDL_GPShutdown(void);

  // 开始记录当前帧的绘制调用。应在设置 SDL_gp 并获取当前帧的交换链纹理和命令缓冲区后调用。
  // 如果返回 false,说明发生错误,应跳过该帧,使用 SDL_GPGetLastError() 获取更多错误信息。
  bool SDL_GPBegin(int width, int height);

  // 将记录的绘制调用刷新到 GPU。如果发生错误返回 false,使用 SDL_GPGetLastError() 获取更多错误信息。
  bool SDL_GPFlush(SDL_GPUCommandBuffer *cmd_buffer, SDL_GPUTexture *texture);

  // 结束当前帧的绘制调用记录。
  void SDL_GPEnd(void);

  // 设置当前视口中坐标空间的边界。
  void SDL_GPSetProjection(float left, float right, float bottom, float top);

  // 将投影重置为默认坐标空间,即当前视口的坐标。
  void SDL_GPResetProjection(void);

  // 将当前变换矩阵保存到变换栈中,供稍后使用 SDL_GPPopTransform 弹出。
  void SDL_GPPushTransform(void);

  // 从变换栈顶部恢复变换矩阵。
  void SDL_GPPopTransform(void);

  // 将当前变换矩阵设置为单位矩阵(无变换)。
  void SDL_GPResetTransform(void);

  // 平移二维坐标空间。
  void SDL_GPTranslate(float x, float y);

  // 绕原点旋转二维坐标空间。
  void SDL_GPRotate(float angle);

  // 绕某一点旋转二维坐标空间。
  void SDL_GPRotateAt(float angle, float ax, float ay);

  // 绕原点缩放二维坐标空间。
  void SDL_GPScale(float sx, float sy);

  // 绕某一点缩放二维坐标空间。
  void SDL_GPScaleAt(float sx, float sy, float ax, float ay);

  // 设置当前图形管线。
  void SDL_GPSetPipeline(SDL_GPPipeline pipeline);

  // 将图形管线重置为内置的默认管线。
  void SDL_GPResetPipeline(void);

  // 为当前管线设置统一数据。
  void SDL_GPSetUniform(const void *vs_data, size_t vs_size, const void *fs_data, size_t fs_size);

  // 将统一数据重置为默认状态(当前状态颜色)。
  void SDL_GPResetUniform(void);

  // 设置当前混合模式。
  void SDL_GPSetBlendMode(SDL_GPBlendMode blend_mode);

  // 将当前混合模式重置为默认混合模式(无混合)。
  void SDL_GPResetBlendMode(void);

  // 设置当前颜色。
  void SDL_GPSetColor(SDL_Color color);

  // 获取当前颜色。
  SDL_Color SDL_GPGetColor(void);

  // 将当前颜色重置为默认颜色(白色)。
  void SDL_GPResetColor(void);

  // 在纹理通道中设置当前绑定的图像。
  void SDL_GPSetImage(int channel, SDL_GPImage image);

  // 从纹理通道中移除当前绑定的图像(无纹理)。
  void SDL_GPUnsetImage(int channel);

  // 将纹理通道中的当前绑定图像重置为默认值(白色纹理)。
  void SDL_GPResetImage(int channel);

  // 在纹理通道中设置当前绑定的采样器。
  void SDL_GPSetSampler(int channel, SDL_GPUSampler *sampler);

  // 从纹理通道中移除当前绑定的采样器(无采样器)。
  void SDL_GPUnsetSampler(int channel);

  // 将纹理通道中的当前绑定采样器重置为默认值(最近邻采样器)。
  void SDL_GPResetSampler(int channel);

  // 设置要绘制到的屏幕区域。
  void SDL_GPViewport(int x, int y, int w, int h);

  // 将视口重置为默认值(0, 0, width, height)。
  void SDL_GPResetViewport(void);

  // 在视口中设置裁剪矩形。
  void SDL_GPScissor(int x, int y, int w, int h);

  // 将裁剪矩形重置为默认值(视口边界)。
  void SDL_GPResetScissor(void);

  // 将所有状态重置为默认值。
  void SDL_GPResetState(void);

  // 用当前颜色清除当前视口。
  void SDL_GPClear(void);

  // 绘制任意图元。
  void SDL_GPDraw(SDL_GPPrimitiveType primitive_type, const SDL_GPVertex *vertices, Uint32 vertices_count);

  // 批量绘制点。
  void SDL_GPDrawPoints(const SDL_GPPoint *points, Uint32 count);

  // 绘制单个点。
  void SDL_GPDrawPoint(SDL_GPPoint point);

  // 批量绘制线段。
  void SDL_GPDrawLines(const SDL_GPLine *lines, Uint32 count);

  // 绘制单条线段。
  void SDL_GPDrawLine(SDL_GPLine line);

  // 绘制线段条带。
  void SDL_GPDrawLinesStrip(const SDL_GPVec2 *points, Uint32 count);

  // 批量绘制三角形。
  void
  SDL_GPDrawFilledTriangles(const SDL_GPTriangle *triangles, Uint32 count);

  // 绘制单个三角形。
  void SDL_GPDrawFilledTriangle(SDL_GPTriangle triangle);

  // 绘制三角形条带。
  void SDL_GPDrawFilledTrianglesStrip(const SDL_GPVec2 *points, Uint32 count);

  // 批量绘制矩形。
  void SDL_GPDrawFilledRects(const SDL_GPRect *rects, Uint32 count);

  // 绘制单个矩形。
  void SDL_GPDrawFilledRect(SDL_GPRect rect);

  // 批量绘制带纹理的矩形。
  void SDL_GPDrawTexturedRects(int channel, const SDL_GPTexturedRect *rects, Uint32 count);

  // 绘制单个带纹理的矩形。
  void SDL_GPDrawTexturedRect(int channel, SDL_GPTexturedRect rect);

赞助

大家好,我是 nsix,一名独立游戏开发者和开源贡献者,正在努力通过自己的工作谋生。

如果你喜欢我创作的内容并愿意支持我,可以考虑在 GitHub Sponsors (https://github.com/sponsors/n67094) 上成为赞助者。每一份支持都意义重大,非常感谢!

你也可以访问我的博客 www.nsix.blog (https://www.nsix.blog) 获取更多关于我工作的更新和见解。

致谢

  • Edubart (https://github.com/edubart) - 原始 sokol_gp 的创建者,他的工作激励我创建了 SDL_gp
  • SDL 团队 (https://github.com/libsdl-org) - 开发和维护 SDL3

许可证

本项目采用 MIT 许可证授权 - 详情请参见 LICENSE 文件。

相似文章

为我的离线渲染器制作一个着色语言

Hacker News Top

作者详细介绍了为其离线CPU渲染器SORT创建的自定义着色语言库——微型着色语言(TSL),并解释了其动机,包括学习、灵活性、Apple Silicon支持以及相比使用OSL减少依赖等。

用高斯泼溅作画

Lobsters Hottest

作者描述了一个交互式绘画工具的开发过程,该工具利用图像的边缘信息来引导二维高斯泼溅作为笔刷笔触,避免了缓慢的梯度下降方法,并产生类似绘画的效果。

编写一个无绑定GPU抽象层

Hacker News Top

一位开发者分享了他们实现的无绑定GPU抽象层Loon GPU,它基于Vulkan 1.3和Metal 4,灵感来自Sebastian Aaltonen的《No Graphics API》博客文章。该库使用GPU指针、顶点拉取和无绑定纹理堆来简化现代图形API。