use std::{ ptr::{null, null_mut}, str::from_utf8, }; use glfw::{Action, Context, Key}; use learn_gl::render_timer::RenderTimer; fn main() { let default_width = 500; let default_height = 500; let mut glfw = glfw::init(glfw::fail_on_errors).expect("msg"); let (mut window, events) = glfw .create_window( default_width, default_height, "learn_gl", glfw::WindowMode::Windowed, ) .expect("msg"); window.set_key_polling(true); window.make_current(); gl::load_with(|s| glfw.get_proc_address_raw(s).unwrap() as *const _); // gl::load_with(|s| window.get_proc_address(s).unwrap() as *const _); unsafe { gl::Viewport(0, 0, default_width as _, default_height as _) }; window.set_framebuffer_size_callback(|_windows, width, height| { unsafe { gl::Viewport(0, 0, width as _, height as _) }; }); let mut render_timer = RenderTimer::new(); // 编译着色器 let vs_src = std::ffi::CString::new(include_str!(".\\shaders\\vs.vert")).unwrap_or_default(); println!("Vs Shader:\n{}", vs_src.to_str().unwrap_or_default()); let vs_ptr = vs_src.as_ptr() as *const i8; let vs = unsafe { gl::CreateShader(gl::VERTEX_SHADER) }; unsafe { gl::ShaderSource(vs, 1, &vs_ptr as _, null()) }; unsafe { gl::CompileShader(vs) }; let mut success = 0; unsafe { gl::GetShaderiv(vs, gl::COMPILE_STATUS, &mut success) }; if success == 0 { let mut log = [0; 512]; unsafe { gl::GetShaderInfoLog(vs, 512, core::ptr::null_mut(), log.as_mut_ptr()) }; let log_u8: [u8; 512] = unsafe { std::mem::transmute(log) }; println!("{}", from_utf8(&log_u8).unwrap()); } let fs_src = std::ffi::CString::new(include_str!(".\\shaders\\fs.frag")).unwrap_or_default(); println!("Fs Shader:\n{}", fs_src.to_str().unwrap_or_default()); let fs_ptr = fs_src.as_ptr() as *const i8; let fs = unsafe { gl::CreateShader(gl::FRAGMENT_SHADER) }; unsafe { gl::ShaderSource(fs, 1, &fs_ptr as _, null()) }; unsafe { gl::CompileShader(fs) }; let mut success = 0; unsafe { gl::GetShaderiv(fs, gl::COMPILE_STATUS, &mut success) }; if success == 0 { let mut log = [0; 512]; unsafe { gl::GetShaderInfoLog(fs, 512, core::ptr::null_mut(), log.as_mut_ptr()) }; let log_u8: [u8; 512] = unsafe { std::mem::transmute(log) }; println!("{}", from_utf8(&log_u8).unwrap()); } // 链接着色器 let sp = unsafe { gl::CreateProgram() }; unsafe { gl::AttachShader(sp, vs) }; unsafe { gl::AttachShader(sp, fs) }; unsafe { gl::LinkProgram(sp) }; let mut success = 0; unsafe { gl::GetProgramiv(sp, gl::LINK_STATUS, &mut success) }; if success == 0 { let mut log = [0; 512]; unsafe { gl::GetProgramInfoLog(sp, 512, null_mut(), log.as_mut_ptr()) }; let log_u8: [u8; 512] = unsafe { std::mem::transmute(log) }; println!("{}", from_utf8(&log_u8).unwrap()); } // 使用程序和删除着色器 unsafe { gl::UseProgram(sp) }; unsafe { gl::DeleteShader(vs) }; unsafe { gl::DeleteShader(fs) }; // 创建VAO let mut vao = 0; unsafe { gl::GenVertexArrays(1, &mut vao) }; unsafe { gl::BindVertexArray(vao) }; // 创建VBO let a: [f32; _] = [-0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0]; let mut vbo: u32 = 0; unsafe { gl::GenBuffers(1, &mut vbo) }; unsafe { gl::BindBuffer(gl::ARRAY_BUFFER, vbo) }; unsafe { gl::BufferData( gl::ARRAY_BUFFER, size_of_val(&a) as _, a.as_ptr() as _, gl::STATIC_DRAW, ) }; // 链接顶点属性 unsafe { gl::VertexAttribPointer( 0, 3, gl::FLOAT, gl::FALSE, (3 * size_of::()) as _, 0 as _, ) }; unsafe { gl::EnableVertexAttribArray(0) }; // 渲染循环 while !window.should_close() { glfw.poll_events(); for (_, event) in glfw::flush_messages(&events) { handle_window_event(&mut window, event); } render(&mut render_timer, sp ,vao); 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), _ => {} } } fn render(render_timer: &mut RenderTimer, sp: u32, vao: u32) { let t = render_timer.time_count() as f32 / 1000.0 as f32; unsafe { gl::ClearColor(t.sin() * 0.5 + 1.0, t.cos() * 0.5 + 1.0, 0.3, 1.0) }; unsafe { gl::Clear(gl::COLOR_BUFFER_BIT) }; unsafe { gl::UseProgram(sp) }; unsafe { gl::BindVertexArray(vao) }; unsafe { gl::DrawArrays(gl::TRIANGLES, 0, 3) }; }