Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/prime31/zig-renderkit
https://github.com/prime31/zig-renderkit
Last synced: 3 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/prime31/zig-renderkit
- Owner: prime31
- Created: 2020-10-31T22:31:11.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2023-09-06T21:32:39.000Z (about 1 year ago)
- Last Synced: 2024-04-28T04:16:09.185Z (6 months ago)
- Language: Zig
- Size: 8.24 MB
- Stars: 66
- Watchers: 5
- Forks: 11
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-zig - zig-renderkit🗒️Cross platform Zig graphics backends with a 2D focus
README
# Zig RenderKit
Cross platform Zig OpenGL backend. `RenderKit` is an API abstraction (very similar to and inspired by Sokol) that wraps calls to OpenGL. It has its own GL function loader so no external loader is required though you can optionally pass in your own GL loader function (`SDL_GL_GetProcAddress` or `glfwGetProcAddress` for example).### GameKit Companion Project
`RenderKit` is just a pure OpenGL API abstraction layer. In order to get something on screen, it requires an OS window and a graphics context. The companion [GameKit repository](https://github.com/prime31/zig-gamekit) provides all of that and more. It has all the high-level abstractions needed to make fast, efficient 2D games. `GameKit` can be used as a standalone framework or as inspiration for using `RenderKit` in your own projects.## Dependencies
RenderKit has just one external dependency: SDL. You can install SDL with the package manager of your choice.### Usage
- clone the repository: `git clone https://github.com/prime31/zig-renderkit`
- in your projects build.zig, pass your `LibExeObjStep` to `addRenderKitToArtifact` in `RenderKit`'s build.zig## RenderKit API
The RenderKit API uses descriptor structs for creating backend objects much like the Metal API or Sokol. Backend objects are passed back as handles to avoid any pointer management being exposed to game code.### Setup and State
General backend setup and management of graphics state.`pub fn setup(desc: RendererDesc, allocator: Allocator) void`
`pub fn shutdown() void`
`pub fn setRenderState(state: RenderState) void`
`pub fn viewport(x: c_int, y: c_int, width: c_int, height: c_int) void`
`pub fn scissor(x: c_int, y: c_int, width: c_int, height: c_int) void`### Images
Loading and updating of GPU textures.`pub fn createImage(desc: ImageDesc) Image`
`pub fn destroyImage(image: Image) void`
`pub fn updateImage(comptime T: type, image: Image, content: []const T) void`### Passes
Offscreen passes (commonly refered to as render targets or framebuffers).`pub fn createPass(desc: PassDesc) Pass`
`pub fn destroyPass(pass: Pass) void`### Render Loop
These are the methods you will use in your main render loop. `beginPass` renders to an offscreen pass and all offscreen rendering should be done first. Once all offscreen rendering is done drawing to the backbuffer is handled via `beginDefaultPass`. Each call to `beginPass/beginDefaultPass` should be followed by a matching call to `endPass`. Finally, when all rendering for the frame is done calling `commitFrame` flushes all the graphics commands.`pub fn beginDefaultPass(action: ClearCommand, width: c_int, height: c_int) void`
`pub fn beginPass(pass: Pass, action: ClearCommand) void`
`pub fn endPass() void`
`pub fn commitFrame() void`### Buffers
Creating and management of buffers (vertex and index).`pub fn createBuffer(comptime T: type, desc: BufferDesc(T)) Buffer`
`pub fn destroyBuffer(buffer: Buffer) void`
`pub fn updateBuffer(comptime T: type, buffer: Buffer, verts: []const T) void`
`pub fn appendBuffer(comptime T: type, buffer: Buffer, verts: []const T) u32`### Bindings
The only short lived player in the API. BufferBindings envelop what you want to render including an index buffer, 1 - 4 vertex buffers and the textures to bind.`pub fn applyBindings(bindings: BufferBindings) void`
`pub fn draw(base_element: c_int, element_count: c_int, instance_count: c_int) void`### Shaders
An important aspect to understand about RenderKit shaders is how the manage uniforms. When you create a shader you have to tell RenderKit what your vertex and fragment uniforms are.`pub fn createShaderProgram(comptime VertUniformT: type, comptime FragUniformT: type, desc: ShaderDesc) ShaderProgram`
`pub fn destroyShaderProgram(shader: ShaderProgram) void`
`pub fn useShaderProgram(shader: ShaderProgram) void`
`pub fn setShaderProgramUniformBlock(comptime UniformT: type, shader: ShaderProgram, stage: ShaderStage, value: *UniformT) void`### Shader Details
It is recommended to use the `ShaderCompileStep` (docs [here](shader_compiler/README.md)) and let RenderKit handle cross-compiling your shaders and generating your uniform structs. Note that only `float` uniforms are supported due to issues with `int`s between the different backends (future considerations). The shader compiler will handle getting alignment and paddings correct automatically. The shader compiler leverages [Sokol Shader Compiler](https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md) and takes GLSL in spitting out GLSL/SPIR-V/Metal shaders and a zig file with your uniform structs. A commented example of a struct generated by the `ShaderCompileStep` is below.There are a few key points to understand with regard to the comptime `metadata` field. While you can handwrite these if you prefer, the compiler can also handle them for you. The `metadata` field contains a required `uniforms` field, that contains the uniforms for your shader. The shader compiler will pack all your uniforms into a single array of `float4`. This lets you update all of them in one single call.
The `images` field (currently only supports fragment shaders) specifies the names of all the images in your shader. RenderKit will automatically find the declarations and bind the correct slots for you.
```zig
pub const DissolveParams = extern struct {
// the comptime metadata used when creating a shader program to initialize the backend details
pub const metadata = .{
// an array of the images that should be setup
.images = .{ "main_tex", "dissolve_tex" },// definition of each uniform along with its type/size. The shader compiler will always pack all data into
// a single array of float4. Only handwritten shaders would need multiple uniforms (one per struct field).
.uniforms = .{ .DissolveParams = .{ .type = .float4, .array_count = 2 } },
};// the runtime fields, generated from the uniforms defined in the shader. Note that the `threshold_color` field
// is automatically aligned for you by the shader compiler.
progress: f32 = 0,
threshold: f32 = 0,
threshold_color: [4]f32 align(16) = [_]f32{0} ** 4,
};
```
Uses [`zgl`](https://github.com/michal-z/zig-gamedev) for loading OpenGL functions