Hello guys i am trying to make a square and update it every time the cursor is moved.In fact everything works fine. i try to prevent a pause in rendering during some window interactions (e.g. resizing). When I move the cursor, rendering becomes slow (I mean the square is not catching up with the cursor). I'm sure I didn't set up the thread correctly.Here is my code. my problem is similar to this one https://stackoverflow.com/questions/32255136/glfw-pollevents-really-really-slow.
// Rust glfw, gl
extern crate gl;
extern crate glfw;
use self::gl::types::*;
use std::ffi::CString;
use std::mem;
use std::os::raw::c_void;
use std::ptr;
use std::str;
use glfw::Context;
use std::sync::mpsc::channel;
use std::sync::mpsc::{Receiver, Sender};
use std::thread::Builder;
#[derive(Debug)]
enum Act {
MouseMove { x: f64, y: f64 },
Close,
}
fn make_div(W: f32, H: f32, x: f32, y: f32, width: f32, height: f32) -> Vec<f32> {
let left: f32 = ((x / (width / 2.0)) - 1.0);
let top: f32 = -((y / (height / 2.0)) - 1.0);
let bottom: f32 = -((y + H) / (height / 2.0) - 1.0);
let right: f32 = ((x + W) / (width / 2.0) - 1.0);
let mut shape: Vec<f32> = vec![];
shape.append(&mut vec![left, bottom]);
shape.append(&mut vec![right, bottom]);
shape.append(&mut vec![right, top]);
shape.append(&mut vec![left, top]);
shape
}
const vertexShaderSource: &str = r#"
#version 330 core
layout (location = 0) in vec3 aPos;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
"#;
const fragmentShaderSource: &str = r#"
#version 330 core
out vec4 FragColor;
void main() {
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
"#;
fn main() {
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
glfw.window_hint(glfw::WindowHint::OpenGlProfile(
glfw::OpenGlProfileHint::Core,
));
#[cfg(target_os = "macos")]
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
let (mut window, events) = glfw
.create_window(300, 300, "Hello this is window", glfw::WindowMode::Windowed)
.expect("Failed to create GLFW window.");
gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
window.set_cursor_pos_polling(true);
let render_context = window.render_context();
let (mut tx, rx): (Sender<Act>, Receiver<Act>) = channel();
let render_task = Builder::new().name("render task".to_string());
let render_task_done = render_task.spawn(move || {
render(render_context, rx);
});
while !window.should_close() {
// glfw.poll_events();
glfw.wait_events();
for (_, event) in glfw::flush_messages(&events) {
handle_window_event(&mut window, event, &mut tx);
}
}
tx.send(Act::Close)
.ok()
.expect("Failed signal to render thread.");
let _ = render_task_done;
}
fn render(mut context: glfw::RenderContext, finish: Receiver<Act>) {
context.make_current();
let mut state_vao: u32 = 0;
let (shaderProgram, VAO) = unsafe {
let vertexShader = gl::CreateShader(gl::VERTEX_SHADER);
let c_str_vert = CString::new(vertexShaderSource.as_bytes()).unwrap();
gl::ShaderSource(vertexShader, 1, &c_str_vert.as_ptr(), ptr::null());
gl::CompileShader(vertexShader);
let mut success = gl::FALSE as GLint;
let mut infoLog = Vec::with_capacity(512);
infoLog.set_len(512 - 1); // subtract 1 to skip the trailing null character
gl::GetShaderiv(vertexShader, gl::COMPILE_STATUS, &mut success);
if success != gl::TRUE as GLint {
gl::GetShaderInfoLog(
vertexShader,
512,
ptr::null_mut(),
infoLog.as_mut_ptr() as *mut GLchar,
);
println!(
"ERROR::SHADER::VERTEX::COMPILATION_FAILED\n{}",
str::from_utf8(&infoLog).unwrap()
);
}
let fragmentShader = gl::CreateShader(gl::FRAGMENT_SHADER);
let c_str_frag = CString::new(fragmentShaderSource.as_bytes()).unwrap();
gl::ShaderSource(fragmentShader, 1, &c_str_frag.as_ptr(), ptr::null());
gl::CompileShader(fragmentShader);
gl::GetShaderiv(fragmentShader, gl::COMPILE_STATUS, &mut success);
if success != gl::TRUE as GLint {
gl::GetShaderInfoLog(
fragmentShader,
512,
ptr::null_mut(),
infoLog.as_mut_ptr() as *mut GLchar,
);
println!(
"ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n{}",
str::from_utf8(&infoLog).unwrap()
);
}
let shaderProgram = gl::CreateProgram();
gl::AttachShader(shaderProgram, vertexShader);
gl::AttachShader(shaderProgram, fragmentShader);
gl::LinkProgram(shaderProgram);
gl::GetProgramiv(shaderProgram, gl::LINK_STATUS, &mut success);
if success != gl::TRUE as GLint {
gl::GetProgramInfoLog(
shaderProgram,
512,
ptr::null_mut(),
infoLog.as_mut_ptr() as *mut GLchar,
);
println!(
"ERROR::SHADER::PROGRAM::COMPILATION_FAILED\n{}",
str::from_utf8(&infoLog).unwrap()
);
}
gl::DeleteShader(vertexShader);
gl::DeleteShader(fragmentShader);
let mut vertices: Vec<f32> = Vec::new();
vertices.append(&mut make_div(100.0, 100.0, 10.0, 10.0, 300.0, 300.0));
let indices = [
// note that we start from 0!
0, 1, 2, // first Triangle
2, 3, 0, // second Triangle
];
let (mut VBO, mut VAO, mut EBO) = (0, 0, 0);
gl::GenVertexArrays(1, &mut VAO);
gl::GenBuffers(1, &mut VBO);
gl::GenBuffers(1, &mut EBO);
gl::BindVertexArray(VAO);
gl::BindBuffer(gl::ARRAY_BUFFER, VBO);
gl::BufferData(
gl::ARRAY_BUFFER,
(vertices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
&vertices[0] as *const f32 as *const c_void,
gl::STATIC_DRAW,
);
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, EBO);
gl::BufferData(
gl::ELEMENT_ARRAY_BUFFER,
(indices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
&indices[0] as *const i32 as *const c_void,
gl::STATIC_DRAW,
);
gl::VertexAttribPointer(
0,
2,
gl::FLOAT,
gl::FALSE,
2 * mem::size_of::<GLfloat>() as GLsizei,
ptr::null(),
);
gl::EnableVertexAttribArray(0);
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
gl::BindVertexArray(0);
(shaderProgram, VAO)
};
state_vao = VAO;
// repeating ..
fn update(x: f32, y: f32) -> u32 {
unsafe {
let mut vertices: Vec<f32> = Vec::new();
vertices.append(&mut make_div(100.0, 100.0, x, y, 300.0, 300.0));
let indices = [
// note that we start from 0!
0, 1, 2, // first Triangle
2, 3, 0, // second Triangle
];
let (mut VBO, mut VAO, mut EBO) = (0, 0, 0);
gl::GenVertexArrays(1, &mut VAO);
gl::GenBuffers(1, &mut VBO);
gl::GenBuffers(1, &mut EBO);
gl::BindVertexArray(VAO);
gl::BindBuffer(gl::ARRAY_BUFFER, VBO);
gl::BufferData(
gl::ARRAY_BUFFER,
(vertices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
&vertices[0] as *const f32 as *const c_void,
gl::STATIC_DRAW,
);
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, EBO);
gl::BufferData(
gl::ELEMENT_ARRAY_BUFFER,
(indices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
&indices[0] as *const i32 as *const c_void,
gl::STATIC_DRAW,
);
gl::VertexAttribPointer(
0,
2,
gl::FLOAT,
gl::FALSE,
2 * mem::size_of::<GLfloat>() as GLsizei,
ptr::null(),
);
gl::EnableVertexAttribArray(0);
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
gl::BindVertexArray(0);
VAO
}
}
loop {
let open = finish.try_recv();
if !open.is_err() {
match open.unwrap() {
Act::MouseMove { x, y } => {
state_vao = update(x as f32, y as f32);
}
Act::Close => {
break;
}
}
}
unsafe {
gl::ClearColor(0.2, 0.3, 0.3, 1.0);
gl::Clear(gl::COLOR_BUFFER_BIT);
gl::Scissor(0, 0, 300, 300);
gl::Enable(gl::SCISSOR_TEST);
gl::UseProgram(shaderProgram);
gl::BindVertexArray(state_vao);
gl::DrawElements(gl::TRIANGLE_FAN, 200, gl::UNSIGNED_INT, ptr::null());
}
context.swap_buffers();
}
glfw::make_context_current(None);
}
fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent, ch: &mut Sender<Act>) {
match event {
glfw::WindowEvent::CursorPos(xpos, ypos) => {
ch.send(Act::MouseMove { x: xpos, y: ypos }).unwrap();
}
_ => {}
}
}