11 releases
Uses new Rust 2024
| 0.3.3 | Aug 24, 2025 |
|---|---|
| 0.3.2 | Aug 19, 2025 |
| 0.2.2 | Aug 10, 2025 |
| 0.1.5 | Aug 2, 2025 |
| 0.1.4 | May 6, 2025 |
#71 in Graphics APIs
610 downloads per month
Used in globject-rs
3MB
42K
SLoC
The OpenGL core functions for Rust
- The main
structandtraitfor you to use areGLCoreandGL. The structGLCorestores all function pointers, andGLhas all OpenGL core function prototype definitions.GLCoreimplements all of the OpenGL core functions that the traitGLdeclared. GLCorederivesDebug,Clone,Copy,PartialEq, andEq, is very handy to use, you can copy it everywhere, it's just a bunch of function pointers.- When created, every function pointer would not be NULL.
If some OpenGL functions are not retrievable by calling
get_proc_address(), for the sake of safety, the function pointer will be replaced by a dummy function that callspanic!()for you to help diagnose which parts of your code are wrong. - OpenGL/ES contexts created from
libEGLare also usable byGLCore. UseeglGetProcAddress()to createGLCore. GLCorealso supports OpenGL ES, with some of the OpenGL functions which don't belong to OpenGL ES not able to be used even if they look like exist in the trait or the struct. Read the specifications of OpenGL ES carefully, and use the supported functions that were supported by OpenGL ES. Using the unsupported functions causespanic!()for you to help diagnose which parts of your code are wrong.
Usage:
- You need a created OpenGL context. The easiest way is to use the
GLFWlibrary that creates a window with an OpenGL context for you.GLFWis crossplatform, so do theglcore. - You need
wglGetProcAddress()on Windows orglxGetProcAddress()on Linux with an X Server that supports GLX, or on the other platform that supports EGL, you haveeglGetProcAddress(). Or something else, to get the function address of the OpenGL functions your system provides. For example, the code below usesGLFWlibrary, it provideswindow.get_proc_address()could do this. - Create the
GLCoreobject by this:let glcore = GLCore::new(|proc_name|your_get_proc_address(proc_name)); - BAM. All of the OpenGL core functions are here callable through the
glcore
Multiple card or multiple thread usage
- If you have more than one graphic card regardless of their vendors are same (e.g. One is NVIDIA, and another is AMD), you can create different OpenGL contexts and environments, or even get one more
get_proc_address()function from your different card vendor APIs. - You can then create one
GLCorein a specific OpenGL context that contains functions from NVIDIA, and anotherGLCorefrom another specific OpenGL context that contains functions from AMD graphic driver, use them at the same time, and let both of the cards compute for you. You can even create some threads dedicated to each OpenGL context, callmake_current()on each thread, and use your cards concurrently.
OpenGL tips
For scene rendering usage
- OpenGL 3.3 is enough for complicated scene rendering, and that's also the most commonly supported version even in some embedded systems.
- By using OpenGL 3.x for scene rendering, you have VBO to manage your meshes, you have shader programs for GPU rendering, you have VAO to link your mesh attrib to a shader program, you have batch rendering command
glDrawXxxxInstanced(),glMultiDrawXxxxxBaseVertex()etc. - The most powerful batch rendering command is
glMultiDrawElementsIndirectbut that needs OpenGL 4.3. - Do not use OpenGL 2.x and 1.x ways to render things, there are too many limitations of using shaders, and if you are not using VBO, drawing any primitive shapes is slow because the shapes or meshes are not stored in the GPU GRAM, every time you want to draw, the CPU send the mesh data to the GPU, that's why it's slow.
For GPU computing usage
- You must have OpenGL 4.3 context, which provides
glDispatchCompute()for GPU computing, it uses shaders, images, and groups jobs in 3 dimensions, almost like using CUDA. - After called this function, the GPU starts computing, and your CPU are not just waiting for it to complete.
- When you have to retrieve the computed result, call
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT), then you can access the images to retrieve it back to your RAM.
Example code
Look at the example of using OpenGL with GLFW:
use glfw::{Action, Context, Key, SwapInterval};
use glcore::*;
fn main() {
let mut glfw = glfw::init(glfw::fail_on_errors).unwrap();
let (mut window, events) = glfw.create_window(640, 480, "Hello this is window", glfw::WindowMode::Windowed)
.expect("Failed to create GLFW window.");
window.set_key_polling(true);
window.make_current();
glfw.set_swap_interval(SwapInterval::Adaptive);
// Look at here, this is the OpenGL core function lib creation
let glcore = GLCore::new(|proc_name|window.get_proc_address(proc_name)).unwrap();
dbg!(glcore);
while !window.should_close() {
glfw.poll_events();
for (_, event) in glfw::flush_messages(&events) {
handle_window_event(&mut window, event);
}
let cur_frame_time = glfw.get_time();
// Call the OpenGL functions here.
glcore.glClearColor(cur_frame_time.sin() as f32, cur_frame_time.cos() as f32, (cur_frame_time * 1.5).sin() as f32, 1.0).unwrap();
glcore.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT).unwrap();
// Because the `GLCore` is the almost naked OpenGL functions provider, I don't want to write some complicated scene rendering codes here.
// Just changes the background color that indicates the OpenGL functions were working.
// Let the GLFW window shows the rendered content for you
window.swap_buffers();
}
}
fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
match event {
glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
window.set_should_close(true)
}
_ => {}
}
}
NOTE
- Make sure only call functions that were provided by your system.
e.g. If your system provides an OpenGL version is 4.0.0, do not try to call 4.1.0 functions.
See the source code of
GLCoreyou will find out which function was introduced from which version of OpenGL. - Create the
GLCoreinside the OpenGL context (which mean after you called yourmake_current()). The OpenGL context and theget_proc_address()behave differently in different graphic card drivers.