From 949d6722f0c77d8c6b12dce47a5fa94a6f507fe9 Mon Sep 17 00:00:00 2001 From: Vegard Matthey Date: Mon, 25 Aug 2025 19:44:28 +0200 Subject: [PATCH] set up VAO --- src/main.rs | 162 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 120 insertions(+), 42 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8617821..76ee11e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,19 +8,28 @@ #![allow(unused_variables)] */ extern crate nalgebra_glm as glm; -use std::{ mem, ptr, os::raw::c_void }; +use std::sync::{Arc, Mutex, RwLock}; use std::thread; -use std::sync::{Mutex, Arc, RwLock}; +use std::{mem, os::raw::c_void, ptr}; mod shader; mod util; -use glutin::event::{Event, WindowEvent, DeviceEvent, KeyboardInput, ElementState::{Pressed, Released}, VirtualKeyCode::{self, *}}; +use glutin::event::{ + DeviceEvent, + ElementState::{Pressed, Released}, + Event, KeyboardInput, + VirtualKeyCode::{self, *}, + WindowEvent, +}; use glutin::event_loop::ControlFlow; // initial window size const INITIAL_SCREEN_W: u32 = 800; const INITIAL_SCREEN_H: u32 = 600; +// TODO: I used the funny number. +const VERTEX_ATTRIBUTE_INDEX: u32 = 3; +const DIMENSIONS: i32 = 2; // == // Helper functions to make interacting with OpenGL a little bit prettier. You *WILL* need these! // == // @@ -51,7 +60,6 @@ fn offset(n: u32) -> *const c_void { // Get a null pointer (equivalent to an offset of 0) // ptr::null() - // == // Generate your VAO here unsafe fn create_vao(vertices: &Vec, indices: &Vec) -> u32 { // Implement me! @@ -66,20 +74,58 @@ unsafe fn create_vao(vertices: &Vec, indices: &Vec) -> u32 { // * Generate a IBO and bind it // * Fill it with data // * Return the ID of the VAO + let mut vao_id = 0; + gl::GenVertexArrays(1, &mut vao_id); + gl::BindVertexArray(vao_id); + let mut vbo_id = 0; + gl::GenBuffers(1, &mut vbo_id); + gl::BindBuffer(gl::ARRAY_BUFFER, vbo_id); + gl::BufferData( + gl::ARRAY_BUFFER, + byte_size_of_array(&vertices), + vertices.as_ptr() as *const c_void, + gl::STATIC_DRAW, + ); + let mut max_vertex_attribs = 0; + gl::GetIntegerv(gl::MAX_VERTEX_ATTRIBS, &mut max_vertex_attribs); + println!("max vertex attributes: {max_vertex_attribs}"); + gl::VertexAttribPointer( + VERTEX_ATTRIBUTE_INDEX, + DIMENSIONS, + gl::FLOAT, + gl::FALSE, + 0, + std::ptr::null(), + ); + gl::EnableVertexAttribArray(VERTEX_ATTRIBUTE_INDEX); - 0 + + let mut index_buf_id = 0; + gl::GenBuffers(1, &mut index_buf_id); + gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buf_id); + gl::BufferData( + gl::ELEMENT_ARRAY_BUFFER, + byte_size_of_array(&indices), + indices.as_ptr() as *const c_void, + gl::STATIC_DRAW, + ); + + gl::DrawElements(gl::TRIANGLES, indices.len() as i32, gl::UNSIGNED_INT, std::ptr::null()); + + vao_id } - fn main() { // Set up the necessary objects to deal with windows and event handling let el = glutin::event_loop::EventLoop::new(); let wb = glutin::window::WindowBuilder::new() .with_title("Gloom-rs") .with_resizable(true) - .with_inner_size(glutin::dpi::LogicalSize::new(INITIAL_SCREEN_W, INITIAL_SCREEN_H)); - let cb = glutin::ContextBuilder::new() - .with_vsync(true); + .with_inner_size(glutin::dpi::LogicalSize::new( + INITIAL_SCREEN_W, + INITIAL_SCREEN_H, + )); + 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"); @@ -125,15 +171,27 @@ fn main() { 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!( + "{}: {}", + 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)); + println!( + "GLSL\t: {}", + util::get_gl_string(gl::SHADING_LANGUAGE_VERSION) + ); } // == // Set up your VAO around here - let my_vao = unsafe { 1337 }; - + let vertices = vec![-1., 0., 1., 0.5]; + let indices = vec![0, 1, 2, 1, 1, 3]; + let my_vao = unsafe { + create_vao(&vertices, &indices); + }; + println!("created vao!"); + // let my_vao = unsafe { 1337 }; // == // Set up your shaders here @@ -144,19 +202,21 @@ fn main() { // This snippet is not enough to do the exercise, and will need to be modified (outside // of just using the correct path), but it only needs to be called once - /* + // TODO: Find out what to do with vertex and fragment shader. let simple_shader = unsafe { shader::ShaderBuilder::new() - .attach_file("./path/to/simple/shader.file") + .attach_file("./shaders/simple.vert") + .link() + }; + let simple_shader = unsafe { + shader::ShaderBuilder::new() + .attach_file("./shaders/simple.frag") .link() }; - */ - // Used to demonstrate keyboard handling for exercise 2. let mut _arbitrary_number = 0.0; // feel free to remove - // The main rendering loop let first_frame_time = std::time::Instant::now(); let mut previous_frame_time = first_frame_time; @@ -174,7 +234,9 @@ fn main() { window_aspect_ratio = new_size.0 as f32 / new_size.1 as f32; (*new_size).2 = false; println!("Window was resized to {}x{}", new_size.0, new_size.1); - unsafe { gl::Viewport(0, 0, new_size.0 as i32, new_size.1 as i32); } + unsafe { + gl::Viewport(0, 0, new_size.0 as i32, new_size.1 as i32); + } } } @@ -184,7 +246,6 @@ fn main() { match key { // The `VirtualKeyCode` enum is defined here: // https://docs.rs/winit/0.25.0/winit/event/enum.VirtualKeyCode.html - VirtualKeyCode::A => { _arbitrary_number += delta_time; } @@ -192,15 +253,13 @@ fn main() { _arbitrary_number -= delta_time; } - // default handler: - _ => { } + _ => {} } } } // 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() { - // == // Optionally access the accumulated mouse movement between // == // frames here with `delta.0` and `delta.1` @@ -209,17 +268,12 @@ fn main() { // == // Please compute camera transforms here (exercise 2 & 3) - unsafe { // Clear the color and depth buffers gl::ClearColor(0.035, 0.046, 0.078, 1.0); // night sky gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT); - // == // Issue the necessary gl:: commands to draw your scene here - - - } // Display the new color buffer on the display @@ -227,12 +281,10 @@ fn main() { } }); - // == // // == // From here on down there are only internals. // == // - // Keep track of the health of the rendering thread let render_thread_healthy = Arc::new(RwLock::new(true)); let render_thread_watchdog = Arc::clone(&render_thread_healthy); @@ -257,19 +309,38 @@ fn main() { } match event { - Event::WindowEvent { event: WindowEvent::Resized(physical_size), .. } => { - println!("New window size received: {}x{}", physical_size.width, physical_size.height); + Event::WindowEvent { + event: WindowEvent::Resized(physical_size), + .. + } => { + println!( + "New window size received: {}x{}", + physical_size.width, physical_size.height + ); if let Ok(mut new_size) = arc_window_size.lock() { *new_size = (physical_size.width, physical_size.height, true); } } - Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { *control_flow = ControlFlow::Exit; } // Keep track of currently pressed keys to send to the rendering thread - Event::WindowEvent { event: WindowEvent::KeyboardInput { - input: KeyboardInput { state: key_state, virtual_keycode: Some(keycode), .. }, .. }, .. } => { - + Event::WindowEvent { + event: + WindowEvent::KeyboardInput { + input: + KeyboardInput { + state: key_state, + virtual_keycode: Some(keycode), + .. + }, + .. + }, + .. + } => { if let Ok(mut keys) = arc_pressed_keys.lock() { match key_state { Released => { @@ -277,7 +348,7 @@ fn main() { let i = keys.iter().position(|&k| k == keycode).unwrap(); keys.remove(i); } - }, + } Pressed => { if !keys.contains(&keycode) { keys.push(keycode); @@ -288,18 +359,25 @@ fn main() { // Handle Escape and Q keys separately match keycode { - Escape => { *control_flow = ControlFlow::Exit; } - Q => { *control_flow = ControlFlow::Exit; } - _ => { } + Escape => { + *control_flow = ControlFlow::Exit; + } + Q => { + *control_flow = ControlFlow::Exit; + } + _ => {} } } - Event::DeviceEvent { event: DeviceEvent::MouseMotion { delta }, .. } => { + 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); } } - _ => { } + _ => {} } }); }