使用各种代码示例,我创建了一个简单的OpenGL应用程序,项目依赖关系如下:
[dependencies]
epoxy = "0.1.0"
gl = "0.14.0"
gtk = { version = "0.7.3", package = "gtk4", features = ["v4_12"] }
libloading = "0.8.1"
字符串
逻辑也很简单:使用GTK+ v4.12和OpenGL上下文初始化一个窗口,并尝试绘制一个三角形。
main.rs
mod renderer;
use gtk::prelude::*;
use gtk::{glib, Application, ApplicationWindow};
use renderer::{on_render, on_realize};
const APP_ID: &str = "com.noobie.teapot";
const APP_NAME: &str = "Teapot";
fn main() -> glib::ExitCode {
init_gl();
// Create a new application
let app = Application::builder()
.application_id(APP_ID)
.build();
// Connect to "activate" signal of `app`
app.connect_activate(on_activate);
// Run the application
app.run()
}
fn init_gl() {
#[cfg(target_os = "macos")]
let library = unsafe { libloading::os::unix::Library::new("libepoxy.0.dylib") }.unwrap();
#[cfg(all(unix, not(target_os = "macos")))]
let library = unsafe { libloading::os::unix::Library::new("libepoxy.so.0") }.unwrap();
#[cfg(windows)]
let library = libloading::os::windows::Library::open_already_loaded("epoxy-0.dll").unwrap();
epoxy::load_with(|name| {
unsafe { library.get::<_>(name.as_bytes()) }
.map(|symbol| *symbol)
.unwrap_or(std::ptr::null())
});
gl::load_with(|s| epoxy::get_proc_addr(s));
}
fn on_activate(app: &Application) {
// Create a window and set the title
let window = ApplicationWindow::builder()
.application(app)
.title(APP_NAME)
.default_width(800)
.default_height(600)
.build();
let container = gtk::Paned::builder()
.orientation(gtk::Orientation::Vertical)
.shrink_end_child(true)
.build();
let gl_area = gtk::GLArea::builder()
.auto_render(false)
.height_request(8)
.build();
gl_area.connect_realize(on_realize);
gl_area.connect_render(on_render);
container.set_start_child(Some(&gl_area));
let grid_view = gtk::GridView::builder()
.height_request(4)
.build();
container.set_end_child(Some(&grid_view));
window.set_child(Some(&container));
// Present window
window.present();
}
型
renderer.rs
use std::mem::{size_of_val, size_of};
use gtk::prelude::*;
use gtk::{glib::Propagation, gdk::GLContext};
type Vertex = [f32; 3];
const VERTICES: [Vertex; 3] = [
[-0.5, -0.5, 0.0],
[0.5, -0.5, 0.0],
[0.0, 0.5, 0.0]
];
const VERT_SHADER: &str = r#"#version 330 core
layout (location = 0) in vec3 pos;
void main() {
gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);
}
"#;
const FRAG_SHADER: &str = r#"#version 330 core
out vec4 final_color;
void main() {
final_color = vec4(1.0, 0.5, 0.2, 1.0);
}
"#;
pub fn on_realize(_gl_area: >k::GLArea) {
}
pub fn on_render(_gl_area: >k::GLArea, _ctx: &GLContext) -> Propagation {
unsafe {
gl::ClearColor(0.3, 0.3, 0.3, 1.0);
let mut vao = 0;
gl::GenVertexArrays(1, &mut vao);
assert_ne!(vao, 0);
let mut vbo = 0;
gl::GenBuffers(1, &mut vbo);
assert_ne!(vbo, 0);
gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
gl::BufferData(gl::ARRAY_BUFFER, size_of_val(&VERTICES) as isize, VERTICES.as_ptr().cast(), gl::STATIC_DRAW);
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, size_of::<Vertex>().try_into().unwrap(), 0 as *const _);
gl::EnableVertexAttribArray(0);
let vertex_shader = gl::CreateShader(gl::VERTEX_SHADER);
assert_ne!(vertex_shader, 0);
gl::ShaderSource(
vertex_shader,
1,
&(VERT_SHADER.as_bytes().as_ptr().cast()),
&(VERT_SHADER.len().try_into().unwrap()),
);
gl::CompileShader(vertex_shader);
let mut success = 0;
gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success);
if success == 0 {
let mut v: Vec<u8> = Vec::with_capacity(1024);
let mut log_len = 0_i32;
gl::GetShaderInfoLog(
vertex_shader,
1024,
&mut log_len,
v.as_mut_ptr().cast(),
);
v.set_len(log_len.try_into().unwrap());
panic!("Vertex Compile Error: {}", String::from_utf8_lossy(&v));
}
let fragment_shader = gl::CreateShader(gl::FRAGMENT_SHADER);
assert_ne!(fragment_shader, 0);
gl::ShaderSource(
fragment_shader,
1,
&(FRAG_SHADER.as_bytes().as_ptr().cast()),
&(FRAG_SHADER.len().try_into().unwrap()),
);
gl::CompileShader(fragment_shader);
gl::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success);
if success == 0 {
let mut v: Vec<u8> = Vec::with_capacity(1024);
let mut log_len = 0_i32;
gl::GetShaderInfoLog(
fragment_shader,
1024,
&mut log_len,
v.as_mut_ptr().cast(),
);
v.set_len(log_len.try_into().unwrap());
panic!("Fragment Compile Error: {}", String::from_utf8_lossy(&v));
}
let shader_program = gl::CreateProgram();
gl::AttachShader(shader_program, vertex_shader);
gl::AttachShader(shader_program, fragment_shader);
gl::LinkProgram(shader_program);
let mut success = 0;
gl::GetProgramiv(shader_program, gl::LINK_STATUS, &mut success);
if success == 0 {
let mut v: Vec<u8> = Vec::with_capacity(1024);
let mut log_len = 0_i32;
gl::GetProgramInfoLog(
shader_program,
1024,
&mut log_len,
v.as_mut_ptr().cast(),
);
v.set_len(log_len.try_into().unwrap());
panic!("Program Link Error: {}", String::from_utf8_lossy(&v));
}
gl::DeleteShader(vertex_shader);
gl::DeleteShader(fragment_shader);
gl::UseProgram(shader_program);
gl::Clear(gl::COLOR_BUFFER_BIT);
gl::DrawArrays(gl::TRIANGLES, 0, 3);
_gl_area.queue_draw();
}
return Propagation::Proceed;
}
型
然而,当我启动我的程序时,它只是显示一个纯灰色:
的数据
我是一个OpenGL的菜鸟,所以我甚至不能得到什么问题。在控制台输出没有任何错误。
1条答案
按热度按时间yacmzcpb1#
你只能看到灰色的原因是因为这是你当前的清晰颜色,三角形没有画在顶部。
据我所知,您当前的实现存在多个问题,我不确定是否有必要通过所有这些问题。
如果你只是想让它工作,这里有一个非常基本的示例,说明renderer.rs的外观:
字符串
它主要基于
gl-rs
的官方triangle example。然而,@BDL的评论当然仍然适用,这里不考虑,这就是为什么我建议你看看(基于
glium
的)OpenGL example ofgtk4-rs
。