{"id":13531324,"url":"https://github.com/edubart/sokol_gp","last_synced_at":"2025-05-15T20:03:44.924Z","repository":{"id":40317206,"uuid":"266784748","full_name":"edubart/sokol_gp","owner":"edubart","description":"Minimal modern efficient cross platform 2D graphics painter in C","archived":false,"fork":false,"pushed_at":"2025-01-09T11:11:53.000Z","size":3881,"stargazers_count":495,"open_issues_count":1,"forks_count":26,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-08T04:11:19.208Z","etag":null,"topics":["2d","c","d3d11","graphics","metal","opengl","rendering","sokol"],"latest_commit_sha":null,"homepage":"https://edubart.github.io/sokol_gp/sample-primitives.html","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit-0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/edubart.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"edubart"}},"created_at":"2020-05-25T13:21:15.000Z","updated_at":"2025-04-06T09:34:46.000Z","dependencies_parsed_at":"2022-08-09T17:10:31.707Z","dependency_job_id":"933d8a76-599e-4ac0-b738-f9ccd1efcbe6","html_url":"https://github.com/edubart/sokol_gp","commit_stats":{"total_commits":141,"total_committers":5,"mean_commits":28.2,"dds":0.04255319148936165,"last_synced_commit":"cfa2733bb28199491ef6d03027d2839e4fe62a40"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edubart%2Fsokol_gp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edubart%2Fsokol_gp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edubart%2Fsokol_gp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edubart%2Fsokol_gp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edubart","download_url":"https://codeload.github.com/edubart/sokol_gp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254414493,"owners_count":22067271,"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":["2d","c","d3d11","graphics","metal","opengl","rendering","sokol"],"created_at":"2024-08-01T07:01:02.060Z","updated_at":"2025-05-15T20:03:40.332Z","avatar_url":"https://github.com/edubart.png","language":"C","funding_links":["https://github.com/sponsors/edubart"],"categories":["Game Programming","Libraries"],"sub_categories":["C"],"readme":"# Sokol GP\n\nMinimal efficient cross platform 2D graphics painter in pure C\nusing modern graphics API through the excellent [Sokol GFX](https://github.com/floooh/sokol) library.\n\nSokol GP, or in short SGP, stands for Sokol Graphics Painter.\n\n[![sample-primitives](https://edubart.github.io/sokol_gp/sample-primitives.png)](https://edubart.github.io/sokol_gp/sample-primitives.html)\n\n## Features\n\n* Made and optimized only for **2D rendering only**, no 3D support.\n* Minimal, in a pure single C header.\n* Use modern unfixed pipeline graphics APIs for more efficiency.\n* Cross platform (backed by Sokol GFX).\n* D3D11/OpenGL 3.3/Metal/WebGPU graphics backends (through Sokol GFX).\n* **Automatic batching** (merge recent draw calls into batches automatically).\n* **Batch optimizer** (rearranges the ordering of draw calls to batch more).\n* Batch draw calls even when using different color states. **\\*NEW\\***\n* Uses preallocated memory (no allocations at runtime).\n* Supports drawing basic 2D primitives (rectangles, triangles, lines and points).\n* Supports the classic 2D color blending modes (color blend, add, modulate, multiply).\n* Supports 2D space transformations and changing 2D space coordinate systems.\n* Supports drawing the basic primitives (rectangles, triangles, lines and points).\n* Supports multiple texture bindings.\n* Supports custom fragment shaders with 2D primitives.\n* Can be mixed with projects that are already using Sokol GFX.\n\n## Why?\n\nSokol GFX is an excellent library for rendering using unfixed pipelines\nof modern graphics cards, but it is too complex to use for simple 2D drawing,\nand it's API is too generic and specialized for 3D rendering. To draw 2D stuff, the programmer\nusually needs to setup custom shaders when using Sokol GFX, or use its Sokol GL\nextra library, but Sokol GL also has an API with 3D design in mind, which\nincurs some costs and limitations.\n\nThis library was created to draw 2D primitives through Sokol GFX with ease,\nand by not considering 3D usage it is optimized for 2D rendering only,\nfurthermore it features an **automatic batch optimizer**, more details of it will be described below.\n\n## Automatic batch optimizer\n\nWhen drawing the library creates a draw command queue of all primitives yet to be drawn,\nevery time a new draw command is added the batch optimizer looks back up to the last\n8 recent draw commands (this is adjustable), and try to rearrange and merge drawing commands\nif it finds a previous draw command that meets the following criteria:\n\n* The new draw command and previous command uses the *same primitive pipeline*\n* The new draw command and previous command uses the *same shader uniforms*\n* The new draw command and previous command uses the *same texture bindings*\n* The new draw command and previous command does not have another intermediary\ndraw command *that overlaps* in-between them.\n\nBy doing this the batch optimizer is able for example to merge textured draw calls,\neven if they were drawn with other intermediary different textures draws between them.\nThe effect is more efficiency when drawing, because less draw calls will be dispatched\nto the GPU,\n\nThis library can avoid a lot of work of making an efficient 2D drawing batching system,\nby automatically merging draw calls behind the scenes at runtime,\nthus the programmer does not need to manage batched draw calls manually,\nnor he needs to sort batched texture draw calls,\nthe library will do this seamlessly behind the scenes.\n\nThe batching algorithm is fast, but it has `O(n)` CPU complexity for every new draw command added,\nwhere `n` is the `SGP_BATCH_OPTIMIZER_DEPTH` configuration.\nIn experiments using `8` as the default is a good default,\nbut you may want to try out different values depending on your case.\nUsing values that are too high is not recommended, because the algorithm may take too long\nscanning previous draw commands, and that may consume more CPU resources.\n\nThe batch optimizer can be disabled by setting `SGP_BATCH_OPTIMIZER_DEPTH` to 0,\nyou can use that to measure its impact.\n\nIn the samples directory of this repository there is a\nbenchmark example that tests drawing with the bath optimizer enabled/disabled.\nOn my machine that benchmark was able to increase performance in a 2.2x factor when it is enabled.\nIn some private game projects the gains of the batch optimizer proved to increase FPS performance\nabove 1.5x by just replacing the graphics backend with this library, with no internal\nchanges to the game itself.\n\n## Design choices\n\nThe library has some design choices with performance in mind that will be discussed briefly here.\n\nLike Sokol GFX, Sokol GP will never do any allocation in the draw loop,\nso when initializing you must configure beforehand the maximum size of the\ndraw command queue buffer and the vertices buffer.\n\nAll the 2D space transformation (functions like `sgp_rotate`) are done by the CPU and not by the GPU,\nthis is intentionally to avoid adding extra overhead in the GPU, because typically the number\nof vertices of 2D applications are not that large, and it is more efficient to perform\nall the transformation with the CPU right away rather than pushing extra buffers to the GPU\nthat ends up using more bandwidth of the CPU\u003c-\u003eGPU bus.\nIn contrast 3D applications usually dispatches vertex transformations to the GPU using a vertex shader,\nthey do this because the amount of vertices of 3D objects can be very large\nand it is usually the best choice, but this is not true for 2D rendering.\n\nMany APIs to transform the 2D space before drawing a primitive are available, such as\ntranslate, rotate and scale. They can be used as similarly as the ones available in 3D graphics APIs,\nbut they are crafted for 2D only, for example when using 2D we don't need to use a 4x4 or 3x3 matrix\nto perform vertex transformation, instead the code is specialized for 2D and can use a 2x3 matrix,\nsaving extra CPU float computations.\n\nAll pipelines always use a texture associated with it, even when drawing non textured primitives,\nbecause this minimizes graphics pipeline changes when mixing textured calls and non textured calls,\nimproving efficiency.\n\nThe library is coded in the style of Sokol GFX headers, reusing many macros from there,\nyou can change some of its semantics such as custom allocator, custom log function, and some\nother details, read `sokol_gfx.h` documentation for more on that.\n\n## Usage\n\nCopy `sokol_gp.h` along with other Sokol headers to the same folder. Setup Sokol GFX\nas you usually would, then add call to `sgp_setup(desc)` just after `sg_setup(desc)`, and\ncall to `sgp_shutdown()` just before `sg_shutdown()`. Note that you should usually check if\nSGP is valid after its creation with `sgp_is_valid()` and exit gracefully with an error if not.\n\nIn your frame draw function add `sgp_begin(width, height)` before calling any SGP\ndraw function, then draw your primitives. At the end of the frame (or framebuffer) you\nshould **ALWAYS call** `sgp_flush()` between a Sokol GFX begin/end render pass,\nthe `sgp_flush()` will dispatch all draw commands to Sokol GFX. Then call `sgp_end()` immediately\nto discard the draw command queue.\n\nAn actual example of this setup will be shown below.\n\n## Quick usage example\n\nThe following is a quick example on how to this library with Sokol GFX and Sokol APP:\n\n```c\n// This is an example on how to set up and use Sokol GP to draw a filled rectangle.\n\n// Includes Sokol GFX, Sokol GP and Sokol APP, doing all implementations.\n#define SOKOL_IMPL\n#include \"sokol_gfx.h\"\n#include \"sokol_gp.h\"\n#include \"sokol_app.h\"\n#include \"sokol_glue.h\"\n#include \"sokol_log.h\"\n\n#include \u003cstdio.h\u003e // for fprintf()\n#include \u003cstdlib.h\u003e // for exit()\n#include \u003cmath.h\u003e // for sinf() and cosf()\n\n// Called on every frame of the application.\nstatic void frame(void) {\n    // Get current window size.\n    int width = sapp_width(), height = sapp_height();\n    float ratio = width/(float)height;\n\n    // Begin recording draw commands for a frame buffer of size (width, height).\n    sgp_begin(width, height);\n    // Set frame buffer drawing region to (0,0,width,height).\n    sgp_viewport(0, 0, width, height);\n    // Set drawing coordinate space to (left=-ratio, right=ratio, top=1, bottom=-1).\n    sgp_project(-ratio, ratio, 1.0f, -1.0f);\n\n    // Clear the frame buffer.\n    sgp_set_color(0.1f, 0.1f, 0.1f, 1.0f);\n    sgp_clear();\n\n    // Draw an animated rectangle that rotates and changes its colors.\n    float time = sapp_frame_count() * sapp_frame_duration();\n    float r = sinf(time)*0.5+0.5, g = cosf(time)*0.5+0.5;\n    sgp_set_color(r, g, 0.3f, 1.0f);\n    sgp_rotate_at(time, 0.0f, 0.0f);\n    sgp_draw_filled_rect(-0.5f, -0.5f, 1.0f, 1.0f);\n\n    // Begin a render pass.\n    sg_pass pass = {.swapchain = sglue_swapchain()};\n    sg_begin_pass(\u0026pass);\n    // Dispatch all draw commands to Sokol GFX.\n    sgp_flush();\n    // Finish a draw command queue, clearing it.\n    sgp_end();\n    // End render pass.\n    sg_end_pass();\n    // Commit Sokol render.\n    sg_commit();\n}\n\n// Called when the application is initializing.\nstatic void init(void) {\n    // Initialize Sokol GFX.\n    sg_desc sgdesc = {\n        .environment = sglue_environment(),\n        .logger.func = slog_func\n    };\n    sg_setup(\u0026sgdesc);\n    if (!sg_isvalid()) {\n        fprintf(stderr, \"Failed to create Sokol GFX context!\\n\");\n        exit(-1);\n    }\n\n    // Initialize Sokol GP, adjust the size of command buffers for your own use.\n    sgp_desc sgpdesc = {0};\n    sgp_setup(\u0026sgpdesc);\n    if (!sgp_is_valid()) {\n        fprintf(stderr, \"Failed to create Sokol GP context: %s\\n\", sgp_get_error_message(sgp_get_last_error()));\n        exit(-1);\n    }\n}\n\n// Called when the application is shutting down.\nstatic void cleanup(void) {\n    // Cleanup Sokol GP and Sokol GFX resources.\n    sgp_shutdown();\n    sg_shutdown();\n}\n\n// Implement application main through Sokol APP.\nsapp_desc sokol_main(int argc, char* argv[]) {\n    (void)argc;\n    (void)argv;\n    return (sapp_desc){\n        .init_cb = init,\n        .frame_cb = frame,\n        .cleanup_cb = cleanup,\n        .window_title = \"Rectangle (Sokol GP)\",\n        .logger.func = slog_func,\n    };\n}\n```\n\nTo run this example, first copy the `sokol_gp.h` header alongside with other Sokol headers\nto the same folder, then compile with any C compiler using the proper linking flags (read `sokol_gfx.h`).\n\n## Complete Examples\n\nIn folder `samples` you can find the following complete examples covering all APIs of the library:\n\n* [sample-primitives.c](https://github.com/edubart/sokol_gp/blob/master/samples/sample-primitives.c): This is an example showing all drawing primitives and transformations APIs.\n* [sample-blend.c](https://github.com/edubart/sokol_gp/blob/master/samples/sample-blend.c): This is an example showing all blend modes between 3 rectangles.\n* [sample-framebuffer.c](https://github.com/edubart/sokol_gp/blob/master/samples/sample-framebuffer.c): This is an example showing how to use multiple `sgp_begin()` with frame buffers.\n* [sample-sdf.c](https://github.com/edubart/sokol_gp/blob/master/samples/sample-sdf.c): This is an example on how to create custom shaders.\n* [sample-effect.c](https://github.com/edubart/sokol_gp/blob/master/samples/sample-effect.c): This is an example on how to use custom shaders for 2D drawing.\n* [sample-bench.c](https://github.com/edubart/sokol_gp/blob/master/samples/sample-bench.c): This is a heavy example used for benchmarking purposes.\n\nThese examples are used as the test suite for the library, you can build them by typing `make`.\n\n## Error handling\n\nIt is possible that after many draw calls the command or vertex buffer may overflow,\nin that case the library will set an error error state and will continue to operate normally,\nbut when flushing the drawing command queue with `sgp_flush()` no draw command will be dispatched.\nThis can happen because the library uses pre allocated buffers, in such\ncases the issue can be fixed by increasing the prefixed command queue buffer and the vertices buffer\nwhen calling `sgp_setup()`.\n\nMaking invalid number of push/pops of `sgp_push_transform()` and `sgp_pop_transform()`,\nor nesting too many `sgp_begin()` and `sgp_end()` may also lead to errors, that\nis a usage mistake.\n\nYou can enable the `SOKOL_DEBUG` macro in such cases to debug, or handle\nthe error programmatically by reading `sgp_get_last_error()` after calling `sgp_end()`.\nIt is also advised to leave `SOKOL_DEBUG` enabled when developing with Sokol, so you can\ncatch mistakes early.\n\n## Blend modes\n\nThe library supports the most usual blend modes used in 2D, which are the following:\n\n- `SGP_BLENDMODE_NONE` - No blending (`dstRGBA = srcRGBA`).\n- `SGP_BLENDMODE_BLEND` - Alpha blending (`dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))` and `dstA = srcA + (dstA * (1-srcA))`)\n- `SGP_BLENDMODE_BLEND_PREMULTIPLIED` - Pre-multiplied alpha blending (`dstRGBA = srcRGBA + (dstRGBA * (1-srcA))`)\n- `SGP_BLENDMODE_ADD` - Additive blending (`dstRGB = (srcRGB * srcA) + dstRGB` and `dstA = dstA`)\n- `SGP_BLENDMODE_ADD_PREMULTIPLIED` - Pre-multiplied additive blending (`dstRGB = srcRGB + dstRGB` and `dstA = dstA`)\n- `SGP_BLENDMODE_MOD` - Color modulate (`dstRGB = srcRGB * dstRGB` and `dstA = dstA`)\n- `SGP_BLENDMODE_MUL` - Color multiply (`dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))` and `dstA = (srcA * dstA) + (dstA * (1-srcA))`)\n\n## Changing 2D coordinate system\n\nYou can change the screen area to draw by calling `sgp_viewport(x, y, width, height)`.\nYou can change the coordinate system of the 2D space by calling `sgp_project(left, right, top, bottom)`,\nwith it.\n\n## Transforming 2D space\n\nYou can translate, rotate or scale the 2D space before a draw call, by using the transformation\nfunctions the library provides, such as `sgp_translate(x, y)`, `sgp_rotate(theta)`, etc.\nCheck the cheat sheet or the header for more.\n\nTo save and restore the transformation state you should call `sgp_push_transform()` and\nlater `sgp_pop_transform()`.\n\n## Drawing primitives\n\nThe library provides drawing functions for all the basic primitives, that is,\nfor points, lines, triangles and rectangles, such as `sgp_draw_line()` and `sgp_draw_filled_rect()`.\nCheck the cheat sheet or the header for more.\nAll of them have batched variations.\n\n## Drawing textured primitives\n\nTo draw textured rectangles you can use `sgp_set_image(0, img)` and then `sgp_draw_filled_rect()`,\nthis will draw an entire texture into a rectangle.\nYou should later reset the image with `sgp_reset_image(0)` to restore the bound image to default white image,\notherwise you will have glitches when drawing a solid color.\n\nIn case you want to draw a specific source from the texture,\nyou should use `sgp_draw_textured_rect()` instead.\n\nBy default textures are drawn using a simple nearest filter sampler,\nyou can change the sampler with `sgp_set_sampler(0, smp)` before drawing a texture,\nit's recommended to restore the default sampler using `sgp_reset_sampler(0)`.\n\n## Color modulation\n\nAll common pipelines have color modulation, and you can modulate\na color before a draw by setting the current state color with `sgp_set_color(r,g,b,a)`,\nlater you should reset the color to default (white) with `sgp_reset_color()`.\n\n## Custom shaders\n\nWhen using a custom shader, you must create a pipeline for it with `sgp_make_pipeline(desc)`,\nusing shader, blend mode and a draw primitive associated with it. Then you should\ncall `sgp_set_pipeline()` before the shader draw call. You are responsible for using\nthe same blend mode and drawing primitive as the created pipeline.\n\nCustom uniforms can be passed to the shader with `sgp_set_uniform(vs_data, vs_size, fs_data, fs_size)`,\nwhere you should always pass a pointer to a struct with exactly the same schema and size\nas the one defined in the vertex and fragment shaders.\n\nAlthough you can create custom shaders for each graphics backend manually,\nit is advised should use the Sokol shader compiler [SHDC](https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md),\nbecause it can generate shaders for multiple backends from a single `.glsl` file,\nand this usually works well.\n\nBy default the library uniform buffer per draw call has just 8 float uniforms\n(`SGP_UNIFORM_CONTENT_SLOTS` configuration), and that may be too low to use with custom shaders.\nThis is the default because typically newcomers may not want to use custom 2D shaders,\nand increasing a larger value means more overhead.\nIf you are using custom shaders please increase this value to be large enough to hold\nthe number of uniforms of your largest shader.\n\n## Library configuration\n\nThe following macros can be defined before including to change the library behavior:\n\n- `SGP_BATCH_OPTIMIZER_DEPTH` - Number of draw commands that the batch optimizer looks back at. Default is 8.\n- `SGP_UNIFORM_CONTENT_SLOTS` - Maximum number of floats that can be stored in each draw call uniform buffer. Default is 8.\n- `SGP_TEXTURE_SLOTS` - Maximum number of textures that can be bound per draw call. Default is 4.\n\n## License\n\nMIT, see LICENSE file or the end of `sokol_gp.h` file.\n\n## Cheat sheet\n\nHere is a quick list of all library functions for quick reference:\n\n```c\n/* Initialization and de-initialization. */\nvoid sgp_setup(const sgp_desc* desc);                 /* Initializes the SGP context, and should be called after `sg_setup`. */\nvoid sgp_shutdown(void);                              /* Destroys the SGP context. */\nbool sgp_is_valid(void);                              /* Checks if SGP context is valid, should be checked after `sgp_setup`. */\n\n/* Error handling. */\nsgp_error sgp_get_last_error(void);                   /* Returns last SGP error. */\nconst char* sgp_get_error_message(sgp_error error);   /* Returns a message with SGP error description. */\n\n/* Custom pipeline creation. */\nsg_pipeline sgp_make_pipeline(const sgp_pipeline_desc* desc); /* Creates a custom shader pipeline to be used with SGP. */\n\n/* Draw command queue management. */\nvoid sgp_begin(int width, int height);    /* Begins a new SGP draw command queue. */\nvoid sgp_flush(void);                     /* Dispatch current Sokol GFX draw commands. */\nvoid sgp_end(void);                       /* End current draw command queue, discarding it. */\n\n/* 2D coordinate space projection */\nvoid sgp_project(float left, float right, float top, float bottom); /* Set the coordinate space boundary in the current viewport. */\nvoid sgp_reset_project(void);                                       /* Resets the coordinate space to default (coordinate of the viewport). */\n\n/* 2D coordinate space transformation. */\nvoid sgp_push_transform(void);                            /* Saves current transform matrix, to be restored later with a pop. */\nvoid sgp_pop_transform(void);                             /* Restore transform matrix to the same value of the last push. */\nvoid sgp_reset_transform(void);                           /* Resets the transform matrix to identity (no transform). */\nvoid sgp_translate(float x, float y);                     /* Translates the 2D coordinate space. */\nvoid sgp_rotate(float theta);                             /* Rotates the 2D coordinate space around the origin. */\nvoid sgp_rotate_at(float theta, float x, float y);        /* Rotates the 2D coordinate space around a point. */\nvoid sgp_scale(float sx, float sy);                       /* Scales the 2D coordinate space around the origin. */\nvoid sgp_scale_at(float sx, float sy, float x, float y);  /* Scales the 2D coordinate space around a point. */\n\n/* State change for custom pipelines. */\nvoid sgp_set_pipeline(sg_pipeline pipeline);              /* Sets current draw pipeline. */\nvoid sgp_reset_pipeline(void);                            /* Resets to the current draw pipeline to default (builtin pipelines). */\nvoid sgp_set_uniform(const void* vs_data, uint32_t vs_size, const void *fs_data, uint32_t fs_size); /* Sets uniform buffer for a custom pipeline. */\nvoid sgp_reset_uniform(void);                             /* Resets uniform buffer to default (current state color). */\n\n/* State change functions for the common pipelines. */\nvoid sgp_set_blend_mode(sgp_blend_mode blend_mode);       /* Sets current blend mode. */\nvoid sgp_reset_blend_mode(void);                          /* Resets current blend mode to default (no blending). */\nvoid sgp_set_color(float r, float g, float b, float a);   /* Sets current color modulation. */\nvoid sgp_reset_color(void);                               /* Resets current color modulation to default (white). */\nvoid sgp_set_image(int channel, sg_image image);          /* Sets current bound image in a texture channel. */\nvoid sgp_unset_image(int channel);                        /* Remove current bound image in a texture channel (no texture). */\nvoid sgp_reset_image(int channel);                        /* Resets current bound image in a texture channel to default (white texture). */\nvoid sgp_set_sampler(int channel, sg_sampler sampler);    /* Sets current bound sampler in a texture channel. */\nvoid sgp_unset_sampler(int channel);                      /* Remove current bound sampler in a texture channel (no sampler). */\nvoid sgp_reset_sampler(int channel);                      /* Resets current bound sampler in a texture channel to default (nearest sampler). */\n\n/* State change functions for all pipelines. */\nvoid sgp_viewport(int x, int y, int w, int h);            /* Sets the screen area to draw into. */\nvoid sgp_reset_viewport(void);                            /* Reset viewport to default values (0, 0, width, height). */\nvoid sgp_scissor(int x, int y, int w, int h);             /* Set clip rectangle in the viewport. */\nvoid sgp_reset_scissor(void);                             /* Resets clip rectangle to default (viewport bounds). */\nvoid sgp_reset_state(void);                               /* Reset all state to default values. */\n\n/* Drawing functions. */\nvoid sgp_clear(void);                                                                         /* Clears the current viewport using the current state color. */\nvoid sgp_draw(sg_primitive_type primitive_type, const sgp_vertex* vertices, uint32_t count);  /* Low level drawing function, capable of drawing any primitive. */\nvoid sgp_draw_points(const sgp_point* points, uint32_t count);                                /* Draws points in a batch. */\nvoid sgp_draw_point(float x, float y);                                                        /* Draws a single point. */\nvoid sgp_draw_lines(const sgp_line* lines, uint32_t count);                                   /* Draws lines in a batch. */\nvoid sgp_draw_line(float ax, float ay, float bx, float by);                                   /* Draws a single line. */\nvoid sgp_draw_lines_strip(const sgp_point* points, uint32_t count);                           /* Draws a strip of lines. */\nvoid sgp_draw_filled_triangles(const sgp_triangle* triangles, uint32_t count);                /* Draws triangles in a batch. */\nvoid sgp_draw_filled_triangle(float ax, float ay, float bx, float by, float cx, float cy);    /* Draws a single triangle. */\nvoid sgp_draw_filled_triangles_strip(const sgp_point* points, uint32_t count);                /* Draws strip of triangles. */\nvoid sgp_draw_filled_rects(const sgp_rect* rects, uint32_t count);                            /* Draws a batch of rectangles. */\nvoid sgp_draw_filled_rect(float x, float y, float w, float h);                                /* Draws a single rectangle. */\nvoid sgp_draw_textured_rects(int channel, const sgp_textured_rect* rects, uint32_t count);    /* Draws a batch textured rectangle, each from a source region. */\nvoid sgp_draw_textured_rect(int channel, sgp_rect dest_rect, sgp_rect src_rect);              /* Draws a single textured rectangle from a source region. */\n\n/* Querying functions. */\nsgp_state* sgp_query_state(void); /* Returns the current draw state. */\nsgp_desc sgp_query_desc(void);    /* Returns description of the current SGP context. */\n```\n\n## Robustness\n\nThis library has been tested since 2020 in private projects,\nand has proved to be stable.\n\n## Sponsorships\n\nThis library has been originally sponsored by the MMORPG game [Medivia Online](https://medivia.online/),\nI would like to thank them for supporting my work.\n\nThanks @kkukshtel for sponsoring batching draw calls with different colors feature.\n\n## Related projects\n\nMake sure to checkout the excellent [Sokol](https://github.com/floooh/sokol) project by @floooh,\nit features many useful single header C libraries made with quality that can be used for game development.\n\nYou may also want to check my other single header C library\n[Minicoro](https://github.com/edubart/minicoro),\nit brings stackful coroutines for C,\nvery useful for simplifying finite state machines in game devlopment.\n\n## Updates\n\n* **06-Dec-2024**: Update to latest Sokol, resulting breaking changes in `sgp_set_uniform` API,\nadded new pre-multiplied blend modes.\n* **27-Jul-2024**: Update to latest Sokol, the OpenGL backend requires now at least GL 4.1.\n* **22-Mar-2024**: Update to latest Sokol, added support for iOS simulator backend.\n* **18-Jan-2024**: Fix shader leaking when creating custom SGP pipelines.\n* **07-Jan-2024**: Make possible to set custom depth format and sample count in pipelines, batch draw calls even when using different colors, introduce low level primitive drawing function, format source files.\n* **31-Oct-2023**: Update to latest Sokol, introduced new WebGPU backend.\n* **30-Sep-2023**: Update to latest Sokol, deprecated GLES2 backend, add image sampler APIs, changes in draw textured APIs.\n* **31-Dec-2021**: The library was open sourced.\n* **05-Aug-2020**: Added support for custom shaders.\n* **03-Jun-2020**: Added the batch optimizer.\n* **29-May-2020**: The library was created.\n\n## Screenshots\n\nHere are some screenshots of all samples in `samples` directory.\nClick on any of the images to view it actually being rendered in realtime in your browser.\n\nPrimitives sample:\n\n[![sample-primitives](https://edubart.github.io/sokol_gp/sample-primitives.png)](https://edubart.github.io/sokol_gp/sample-primitives.html)\n\nBlending modes samples:\n\n[![sample-blend](https://edubart.github.io/sokol_gp/sample-blend.png)](https://edubart.github.io/sokol_gp/sample-blend.html)\n\nFrame buffer sample:\n\n[![sample-framebuffer](https://edubart.github.io/sokol_gp/sample-framebuffer.png)](https://edubart.github.io/sokol_gp/sample-framebuffer.html)\n\nRectangle sample:\n\n[![sample-rectangle](https://edubart.github.io/sokol_gp/sample-rectangle.png)](https://edubart.github.io/sokol_gp/sample-rectangle.html)\n\nEffect sample:\n\n[![sample-effect](https://edubart.github.io/sokol_gp/sample-effect.png)](https://edubart.github.io/sokol_gp/sample-effect.html)\n\nSDF sample:\n\n[![sample-sdf](https://edubart.github.io/sokol_gp/sample-sdf.png)](https://edubart.github.io/sokol_gp/sample-sdf.html)\n\n## Donation\n\nI'm a full-time open source developer, any amount of the donation through my GitHub will be appreciated and could bring me encouragement to keep supporting this and other open source projects.\nI may accept one-time sponsorships for small features or minor enhancements aligned with the project goals, in this case contact me.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedubart%2Fsokol_gp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedubart%2Fsokol_gp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedubart%2Fsokol_gp/lists"}