首页 > 解决方案 > Rust 和 OpenGL 设置

问题描述

我正在尝试将我的 OpenGL 游戏从 C++ 导出到 Rust 并实现两件事:
1. 将 OpenGL 错误消息打印到控制台。
2. 在我的 IDE (Visual Studio Code) 中自动完成 GL 函数和常量。

我用gl_generator crate简单地生成了 OpenGL 绑定并将文件复制bindings.rs到我的货物中。

extern crate sdl2;
mod bindings;
use bindings as GL;

fn main() {
    let sdl = sdl2::init().unwrap();
    let mut event_pump = sdl.event_pump().unwrap();

    let video_subsystem = sdl.video().unwrap();

    let gl_attr = video_subsystem.gl_attr();
    gl_attr.set_context_profile(sdl2::video::GLProfile::Core);
    gl_attr.set_context_version(4, 5);

    let window = video_subsystem.window("Window", 900, 700).opengl().resizable().build().unwrap();
    let _gl_context = window.gl_create_context().unwrap();

    let gl = GL::Gl::load_with(|s| video_subsystem.gl_get_proc_address(s) as *const std::os::raw::c_void);

    unsafe{ gl.Viewport(0, 0, 900, 700); }

    'main: loop { 

        unsafe {
            gl.UseProgram(42); // <- error (^ GL error triggered: 1281)
            gl.ClearColor(0.0, 0.3, 0.6, 1.0 );
            gl.Clear(GL::COLOR_BUFFER_BIT);
        }

        window.gl_swap_window();

        for event in event_pump.poll_iter() {
            match event {
                sdl2::event::Event::Quit {..} => { break 'main },
                _ => {},
            }
        }

    }
}

问题是gl存储所有函数的变量不是全局变量,我不确定如何将它与不同的模块/函数一起使用。
所有函数都在Glstruct 内部的原因是因为我DebugStructGenerator在构建函数中使用了。它不仅打印错误,还打印所有 OpenGL 函数调用(例如,[OpenGL] ClearColor(0.0, 0.3, 0.6, 1.0))。如果它只打印错误消息会很棒。

我的build.rs文件:

extern crate gl_generator;

use gl_generator::{Registry, Fallbacks, /*StructGenerator, GlobalGenerator,*/ DebugStructGenerator, Api, Profile};
use std::env;
use std::fs::File;
use std::path::Path;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let mut file_gl = File::create(&Path::new(&out_dir).join("bindings.rs")).unwrap();
    let registry = Registry::new(Api::Gl, (4, 5), Profile::Core, Fallbacks::All, [ "GL_NV_command_list" ]);
    registry.write_bindings(DebugStructGenerator, &mut file_gl).unwrap();
}

标签: openglrust

解决方案


无需包含 bindings.rs:

pub mod gl {
    include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
}

将此包含在您的main.rslib.rs 中。然后,您可以将任何模块中的 gl 函数包含在其中(因为 gl 包含为 pub 模块):

// anywhere in a module
use crate::gl;            // static gl with lot of constants e.g gl::ARRAY_BUFFER
use crate::gl::Gl;        // gl instance struct with gl: &Gl => gl.bindBuffer(...)
use crate::gl::types::*;  // include all gl types like GLuint, GLenum, ...

由于我们处于生锈状态,您需要将 gl 实例提供给您的函数作为参考或任何您想要的。

也许检查lazy_static,它可以用作全局变量:

lazy_static! {
    pub static ref gl: gl::Gl = create_opengl_context();
}

第一次访问 gl 将调用创建上下文函数。重复调用将使用创建的实例。

也许可以在https://github.com/Kaiser1989/game-glhttps://github.com/Kaiser1989/rust-android-example上查看我的 game-gl 库(图形分支) 。(Android 和 Windows openGL 游戏循环框架)。


推荐阅读