This is an extern "C"-heavy and unsafe template for getting started with OpenGL in Rust, using SDL3. The hope is that you will find value, and base your next project on it- unless the very design of it discourages you away.
Rust gamedev is not quite mature, and some of the choices made here may turn out to be not the best ones as the ecosystem evolves:
-
SDL3: I mainly chose raw SDL3 over GLFW or a Rust-native solutions because it has audio too. I reckon SDL2 will be maintained for quite some time but it will probably not get any new features.
sdl3-syscrate provides slightly more ergonomic bindings than a rawbindgenconversion.sdl3crate does not have feature-parity withsdl3-sysyet.
-
C GLAD: There are a number of OpenGL wrappers for Rust, but unfortunately some have bitrotten and others have too little traction to be dependable. Taking the matters into your own hands may be a good idea.
- Notably, not all bindings support 4.6 SPIR-V stuff.
- Sticking to the standard is not a bad idea.
-
OpenGL: Currently, crates like
raylib-rsprovide a more ergonomic (albeit non-standard) graphics API, so you may want to re-evaluate whether you really need OpenGL.
- Probably don't fork this repository! Copy the code over and start from scratch.
- Go to
glad.dav1d.deand generate your own bindings with your favorite extensions, alongwith its loader. - Replace my bindings in
glad-sys/cc/directory with yours.- Apologies for the dirtiness! A much better way would be to generate bindings directly from the Khronos spec but
gl_generatornot getting updates is this template's raison d'être!
- Apologies for the dirtiness! A much better way would be to generate bindings directly from the Khronos spec but
- If in the far future, consider bumping some of the version numbers.
sdl3-sysis still in churn; specify an exact version number insdl3-experiment/Cargo.tomlinstead of a wildcard if doing a more serious projects.- Repository lacks a
Cargo.lockfor similar reasons. Commit yours into your repo!
Note that there are some guardrails in place, but not nearly enough! I hope to update this template as I find more sharp edges.
Note
One interesting Rust quirk is that the equivalent C function pointer type is always wrapped in Option. This is unlike pointers to any other raw type. There is some helper code to unwrap everything before use. struct GL is a part of it and it contains unwrapped function pointers.
Unfortunately, this hits another quirk of Rust where a.B() only ever means calling method B impl ed on a and not invoking a function pointer. This leads to code that looks like:
let mut gl = GL::unwrap();
(gl.Clear)(GL_COLOR_BUFFER_BIT);
which is ugly. A better wrapper may come in the future.
This repository incorporates code from the following third-parties:
- SDL3 under zlib license
sdl3-sysunder zlib license- GLAD under ??? (which include
khrplatform.hthat is under ???)
To stay in line with SDL, this repository is also licensed under Zlib license.