From 8b22b76286917b52aa795a54f3f4eadbc5b61451 Mon Sep 17 00:00:00 2001 From: Michael Gimle Date: Sat, 5 Sep 2020 07:59:00 +0200 Subject: [PATCH] Diagnostics, mouse input support, uniform location retrieval support for Shader --- src/main.rs | 54 ++++++++++++++++++++++++++++++++++++++------------- src/shader.rs | 12 ++++++++++++ src/util.rs | 4 ++++ 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6161a57..2839b55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,18 @@ extern crate nalgebra_glm as glm; -use gl::types::*; -use std::{ - mem, - ptr, - str, - os::raw::c_void, -}; +use std::{ mem, ptr, os::raw::c_void }; use std::thread; use std::sync::{Mutex, Arc, RwLock}; mod shader; mod util; -use glutin::event::{Event, WindowEvent, KeyboardInput, ElementState::{Pressed, Released}, VirtualKeyCode::{self, *}}; +use glutin::event::{Event, WindowEvent, DeviceEvent, KeyboardInput, ElementState::{Pressed, Released}, VirtualKeyCode::{self, *}}; use glutin::event_loop::ControlFlow; const SCREEN_W: u32 = 800; const SCREEN_H: u32 = 600; -// Helper functions to make interacting with OpenGL a little bit prettier. You will need these! +// == // Helper functions to make interacting with OpenGL a little bit prettier. You *WILL* need these! // == // // The names should be pretty self explanatory fn byte_size_of_array(val: &[T]) -> isize { std::mem::size_of_val(&val[..]) as isize @@ -39,6 +33,11 @@ fn offset(n: u32) -> *const c_void { (n * mem::size_of::() as u32) as *const T as *const c_void } +// Get a null pointer (equivalent to an offset of 0) +// ptr::null() + + + // == // Modify and complete the function below for the first task // unsafe fn FUNCTION_NAME(ARGUMENT_NAME: &Vec, ARGUMENT_NAME: &Vec) -> u32 { } @@ -52,15 +51,23 @@ fn main() { let cb = glutin::ContextBuilder::new() .with_vsync(true); let windowed_context = cb.build_windowed(wb, &el).unwrap(); + // Uncomment these if you want to use the mouse for controls, but want it to be confined to the screen and/or invisible. + // windowed_context.window().set_cursor_grab(true).expect("failed to grab cursor"); + // windowed_context.window().set_cursor_visible(false); // Set up a shared vector for keeping track of currently pressed keys let arc_pressed_keys = Arc::new(Mutex::new(Vec::::with_capacity(10))); - // Send a copy of this vector to send to the render thread + // Make a reference of this vector to send to the render thread let pressed_keys = Arc::clone(&arc_pressed_keys); + // Set up shared tuple for tracking mouse movement between frames + let arc_mouse_delta = Arc::new(Mutex::new((0f32, 0f32))); + // Make a reference of this tuple to send to the render thread + let mouse_delta = Arc::clone(&arc_mouse_delta); + // Spawn a separate thread for rendering, so event handling doesn't block rendering let render_thread = thread::spawn(move || { - // Acquire the OpenGL Context and load the function pointers. This has to be done inside of the renderin thread, because + // Acquire the OpenGL Context and load the function pointers. This has to be done inside of the rendering thread, because // an active OpenGL context cannot safely traverse a thread boundary let context = unsafe { let c = windowed_context.make_current().unwrap(); @@ -76,6 +83,11 @@ fn main() { gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); gl::Enable(gl::DEBUG_OUTPUT_SYNCHRONOUS); gl::DebugMessageCallback(Some(util::debug_callback), ptr::null()); + + // Print some diagnostics + println!("{}: {}", util::get_gl_string(gl::VENDOR), util::get_gl_string(gl::RENDERER)); + println!("OpenGL\t: {}", util::get_gl_string(gl::VERSION)); + println!("GLSL\t: {}", util::get_gl_string(gl::SHADING_LANGUAGE_VERSION)); } // == // Set up your VAO here @@ -85,8 +97,11 @@ fn main() { // Basic usage of shader helper // The code below returns a shader object, which contains the field .program_id - // The snippet is not enough to do the assignment, and will need to be modified (outside of just using the correct path) - // shader::Shaderbuilder::new().attach_file("./path/to/shader").link(); + // The snippet is not enough to do the assignment, and will need to be modified (outside of just using the correct path), but it only needs to be called once + // shader::ShaderBuilder::new().attach_file("./path/to/shader").link(); + unsafe { + + } // Used to demonstrate keyboard handling -- feel free to remove let mut _arbitrary_number = 0.0; @@ -116,6 +131,13 @@ fn main() { } } } + // Handle mouse movement. delta contains the x and y movement of the mouse since last frame in pixels + if let Ok(mut delta) = mouse_delta.lock() { + + + + *delta = (0.0, 0.0); + } unsafe { gl::ClearColor(0.163, 0.163, 0.163, 1.0); @@ -189,6 +211,12 @@ fn main() { _ => { } } }, + Event::DeviceEvent { event: DeviceEvent::MouseMotion { delta }, .. } => { + // Accumulate mouse movement + if let Ok(mut position) = arc_mouse_delta.lock() { + *position = (position.0 + delta.0 as f32, position.1 + delta.1 as f32); + } + }, _ => { } } }); diff --git a/src/shader.rs b/src/shader.rs index 191e9f3..76c0801 100644 --- a/src/shader.rs +++ b/src/shader.rs @@ -24,6 +24,17 @@ pub enum ShaderType { Geometry, } +impl Shader { + // Make sure the shader is active before calling this + pub unsafe fn get_uniform_location(&self, name: &str) -> i32 { + gl::GetUniformLocation(self.program_id, CString::new(name).expect("CString::new failed").as_ptr()) + } + + pub unsafe fn activate(&self) { + gl::UseProgram(self.program_id); + } +} + impl Into for ShaderType { fn into(self) -> gl::types::GLenum { match self { @@ -121,6 +132,7 @@ impl ShaderBuilder { true } + #[must_use = "The shader program is useless if not stored in a variable."] pub unsafe fn link(self) -> Shader { for &shader in &self.shaders { gl::AttachShader(self.program_id, shader); diff --git a/src/util.rs b/src/util.rs index b3ca0b0..18fe0f4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,5 +1,9 @@ use std::ffi::CString; +pub unsafe fn get_gl_string(name: gl::types::GLenum) -> String { + std::ffi::CStr::from_ptr(gl::GetString(name) as *mut i8).to_string_lossy().to_string() +} + // Debug callback to panic upon enountering any OpenGL error pub extern "system" fn debug_callback( source: u32, e_type: u32, id: u32,