From 120447eacf9cb2f0df2285435d255caef4ec60f0 Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Thu, 22 Aug 2024 12:12:25 +0000 Subject: [PATCH] dev --- Cargo.toml | 11 +++ config.toml | 9 ++ src/main.rs | 273 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 293 insertions(+) create mode 100644 Cargo.toml create mode 100644 config.toml create mode 100644 src/main.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..ab49493 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "rust_opengl_helloworld" +version = "1.0.0" +edition = "2021" + +[dependencies] +gl = "0.14.0" +glfw = { version = "0.57.0", features = ["wayland"] } +#bytemuck = "1" +#ogl33 = { version = "0.2.0", features = ["debug_error_checks"]} +#beryllium = "0.13.3" diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..6261155 --- /dev/null +++ b/config.toml @@ -0,0 +1,9 @@ +[build] +rustflags = ["-C", "target-feature=+crt-static"] + +[profile.release] +opt-level = 'z' # Optimize for size +lto = true # Enable link-time optimization +codegen-units = 1 # Reduce number of codegen units to increase optimizations +panic = 'abort' # Abort on panic +strip = true # Strip symbols from binary* diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..a7d5ecb --- /dev/null +++ b/src/main.rs @@ -0,0 +1,273 @@ +use std::convert::TryInto; + +use glfw; +use glfw::Context; +use gl; + +const WIDTH: u32 = 480; +const HEIGHT: u32 = 320; +const TITLE: &str = "Hello From OpenGL World!"; + +fn main() { + use glfw::fail_on_errors; + let mut glfw = glfw::init(fail_on_errors!()).unwrap(); + glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3)); + glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core)); + glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true)); + glfw.window_hint(glfw::WindowHint::Resizable(true)); + + let (mut window, events) = glfw.create_window(WIDTH, HEIGHT, TITLE, glfw::WindowMode::Windowed).unwrap(); + let (screen_width, screen_height) = window.get_framebuffer_size(); + + window.make_current(); + window.set_key_polling(true); + window.set_pos_polling(true); + window.set_all_polling(true); + window.set_size_polling(true); + window.set_close_polling(true); + window.set_refresh_polling(true); + window.set_focus_polling(true); + window.set_iconify_polling(true); + window.set_framebuffer_size_polling(true); + window.set_char_polling(true); + window.set_char_mods_polling(true); + window.set_mouse_button_polling(true); + window.set_cursor_pos_polling(true); + window.set_cursor_enter_polling(true); + window.set_scroll_polling(true); + window.set_maximize_polling(true); + window.set_content_scale_polling(true); + gl::load_with(|ptr| window.get_proc_address(ptr) as *const _); + + unsafe { + gl::Viewport(0, 0, screen_width, screen_height); + clear_color(Color(0.4, 0.4, 0.4, 1.0)); + } + // ------------------------------------------- + + const VERT_SHADER: &str = "#version 330 core + layout (location = 0) in vec3 position; + + void main() + { + gl_Position = vec4(position, 1.0); + // gl_Position = vec4(position.xyz, 1.0); + // gl_Position = vec4(position.x, position.y, position.z, 1.0); + }"; + + const FRAG_SHADER: &str = "#version 330 core + out vec4 Color; + void main() + { + Color = vec4(0.9, 0.5, 0.2, 1.0); + }"; + + let vertex_shader = unsafe { gl::CreateShader(gl::VERTEX_SHADER) }; + unsafe { + gl::ShaderSource(vertex_shader, 1, &VERT_SHADER.as_bytes().as_ptr().cast(), &VERT_SHADER.len().try_into().unwrap()); + gl::CompileShader(vertex_shader); + + let mut success = 0; + gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success); + if success == 0 { + let mut log_len = 0_i32; + // gl::GetShaderiv(vertex_shader, gl::INFO_LOG_LENGTH, &mut log_len); + // let mut v: Vec = Vec::with_capacity(log_len as usize); + // gl::GetShaderInfoLog(vertex_shader, log_len, &mut log_len, v.as_mut_ptr().cast()); + let mut v: Vec = Vec::with_capacity(1024); + gl::GetShaderInfoLog(vertex_shader, 1024, &mut log_len, v.as_mut_ptr().cast()); + v.set_len(log_len.try_into().unwrap()); + panic!("Vertex Shader Compile Error: {}", String::from_utf8_lossy(&v)); + } + } + + let fragment_shader = unsafe { gl::CreateShader(gl::FRAGMENT_SHADER) }; + unsafe { + gl::ShaderSource(fragment_shader, 1, &FRAG_SHADER.as_bytes().as_ptr().cast(), &FRAG_SHADER.len().try_into().unwrap()); + gl::CompileShader(fragment_shader); + + let mut success = 0; + gl::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success); + if success == 0 { + let mut v: Vec = Vec::with_capacity(1024); + let mut log_len = 0_i32; + gl::GetShaderInfoLog(fragment_shader, 1024, &mut log_len, v.as_mut_ptr().cast()); + v.set_len(log_len.try_into().unwrap()); + panic!("Fragment Shader Compile Error: {}", String::from_utf8_lossy(&v)); + } + } + + let shader_program = unsafe { gl::CreateProgram() }; + unsafe { + gl::AttachShader(shader_program, vertex_shader); + gl::AttachShader(shader_program, fragment_shader); + gl::LinkProgram(shader_program); + + let mut success = 0; + gl::GetProgramiv(shader_program, gl::LINK_STATUS, &mut success); + if success == 0 { + let mut v: Vec = Vec::with_capacity(1024); + let mut log_len = 0_i32; + gl::GetProgramInfoLog(shader_program, 1024, &mut log_len, v.as_mut_ptr().cast()); + v.set_len(log_len.try_into().unwrap()); + panic!("Program Link Error: {}", String::from_utf8_lossy(&v)); + } + + gl::DetachShader(shader_program, vertex_shader); + gl::DetachShader(shader_program, fragment_shader); + gl::DeleteShader(vertex_shader); + gl::DeleteShader(fragment_shader); + } + + let vertecies = [ + -0.5f32, -0.5, 0.0, + 0.5, -0.5, 0.0, + 0.0, 0.5, 0.0, + ]; + + let mut vao = 0; + unsafe { gl::GenVertexArrays(1, &mut vao) }; + + let mut vbo = 0; + unsafe { gl::GenBuffers(1, &mut vbo) }; + + unsafe { + gl::BindVertexArray(vao); + + gl::BindBuffer(gl::ARRAY_BUFFER, vbo); + gl::BufferData(gl::ARRAY_BUFFER, std::mem::size_of_val(&vertecies) as isize, vertecies.as_ptr().cast(), gl::STATIC_DRAW); + + gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, 3 * std::mem::size_of::() as i32, 0 as *const _); + gl::EnableVertexAttribArray(0); + + gl::BindBuffer(gl::ARRAY_BUFFER, 0); + gl::BindVertexArray(0); + } + + // ------------------------------------------- + println!("OpenGL version: {}", gl_get_string(gl::VERSION)); + println!("GLSL version: {}", gl_get_string(gl::SHADING_LANGUAGE_VERSION)); + + + while !window.should_close() { + glfw.poll_events(); + for (time, event) in glfw::flush_messages(&events) { + glfw_handle_event(&mut window, time, event); + } + + clear_color(Color(0.3, 0.4, 0.6, 1.0)); + + unsafe { + gl::Clear(gl::COLOR_BUFFER_BIT); + } + + unsafe { + gl::UseProgram(shader_program); + gl::BindVertexArray(vao); + + gl::DrawArrays(gl::TRIANGLES, 0, 3); + + gl::BindVertexArray(0); + } + + window.swap_buffers(); + } +} + +pub struct Color(f32, f32, f32, f32); + +pub fn clear_color(c: Color) { + unsafe { gl::ClearColor(c.0, c.1, c.2, c.3) } +} + +pub fn gl_get_string<'a>(name: gl::types::GLenum) -> &'a str { + let v = unsafe { gl::GetString(name) }; + let v: &std::ffi::CStr = unsafe { std::ffi::CStr::from_ptr(v as *const i8) }; + v.to_str().unwrap() +} + +fn glfw_handle_event(window: &mut glfw::Window, time: f64, event: glfw::WindowEvent) { + use glfw::WindowEvent as Event; + use glfw::Key; + use glfw::Action; + + match event { + Event::Pos(x, y) => { + window.set_title(&format!("Time: {:?}, Window pos: ({:?}, {:?})", time, x, y)) + } + Event::Size(w, h) => window.set_title(&format!( + "Time: {:?}, Window size: ({:?}, {:?})", + time, w, h + )), + Event::Close => println!("Time: {:?}, Window close requested.", time), + Event::Refresh => { + println!("Time: {:?}, Window refresh callback triggered.", time) + } + Event::Focus(true) => println!("Time: {:?}, Window focus gained.", time), + Event::Focus(false) => println!("Time: {:?}, Window focus lost.", time), + Event::Iconify(true) => println!("Time: {:?}, Window was minimised", time), + Event::Iconify(false) => println!("Time: {:?}, Window was maximised.", time), + Event::FramebufferSize(w, h) => { + unsafe { + gl::Viewport(0, 0, w, h); + } + println!("Time: {:?}, Framebuffer size: ({:?}, {:?})", time, w, h) + } + Event::Char(character) => { + println!("Time: {:?}, Character: {:?}", time, character) + } + Event::CharModifiers(character, mods) => println!( + "Time: {:?}, Character: {:?}, Modifiers: [{:?}]", + time, character, mods + ), + Event::MouseButton(btn, action, mods) => println!( + "Time: {:?}, Button: {:?}, Action: {:?}, Modifiers: [{:?}]", + time, + glfw::DebugAliases(btn), + action, + mods + ), + Event::CursorPos(xpos, ypos) => window.set_title(&format!( + "Time: {:?}, Cursor position: ({:?}, {:?})", + time, xpos, ypos + )), + Event::CursorEnter(true) => { + println!("Time: {:?}, Cursor entered window.", time) + } + Event::CursorEnter(false) => println!("Time: {:?}, Cursor left window.", time), + Event::Scroll(x, y) => window.set_title(&format!( + "Time: {:?}, Scroll offset: ({:?}, {:?})", + time, x, y + )), + /*Event::Key(key, scancode, action, mods) => { + println!( + "Time: {:?}, Key: {:?}, ScanCode: {:?}, Action: {:?}, Modifiers: [{:?}]", + time, key, scancode, action, mods + ); + match (key, action) { + (Key::Escape, Action::Press) => window.set_should_close(true), + (Key::R, Action::Press) => { + // Resize should cause the window to "refresh" + let (window_width, window_height) = window.get_size(); + window.set_size(window_width + 1, window_height); + window.set_size(window_width, window_height); + } + _ => {} + } + }*/ + Event::FileDrop(paths) => { + println!("Time: {:?}, Files dropped: {:?}", time, paths) + } + Event::Maximize(maximized) => { + println!("Time: {:?}, Window maximized: {:?}.", time, maximized) + } + Event::ContentScale(xscale, yscale) => println!( + "Time: {:?}, Content scale x: {:?}, Content scale y: {:?}", + time, xscale, yscale + ), + Event::Key(Key::Escape, _, Action::Press, _) => { + window.set_should_close(true); + }, + _ => {}, + } +} \ No newline at end of file