Diagnostics, mouse input support, uniform location retrieval support for Shader

This commit is contained in:
Michael Gimle
2020-09-05 07:59:00 +02:00
parent fca8bf0a42
commit 8b22b76286
3 changed files with 57 additions and 13 deletions

View File

@@ -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<T>(val: &[T]) -> isize {
std::mem::size_of_val(&val[..]) as isize
@@ -39,6 +33,11 @@ fn offset<T>(n: u32) -> *const c_void {
(n * mem::size_of::<T>() 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<f32>, ARGUMENT_NAME: &Vec<u32>) -> 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::<VirtualKeyCode>::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);
}
},
_ => { }
}
});

View File

@@ -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<gl::types::GLenum> 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);

View File

@@ -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,