From 219fc7f57fcf0bfe69cd9280fa68de5d1947a7dd Mon Sep 17 00:00:00 2001 From: Melik Houij Date: Wed, 8 Mar 2023 15:09:25 +0100 Subject: [PATCH] Runs, however buggy --- Cargo.toml | 1 - src/main.rs | 25 ++++++------ src/model.rs | 55 ++++++++++++--------------- src/model/mesh.rs | 96 ++++++++++++++++++++++++++--------------------- src/shader.rs | 10 ++--- 5 files changed, 96 insertions(+), 91 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d84d453..9742bb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ edition = "2021" [dependencies] field-offset = "0.3.4" image = "0.24.5" -gl = "0.14.0" cgmath = "0.18.0" tobj = "2.0.0" glow = "0.12.1" diff --git a/src/main.rs b/src/main.rs index 492e3ea..5e3d8e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use glfw; use glfw::{Action, Context, Key}; use cgmath::{Matrix4, vec3, Point3, Deg, perspective}; use cgmath::prelude::*; +use std::rc::Rc; const SCR_WIDTH: u32 = 1600; const SCR_HEIGHT: u32 = 900; const TITLE: &str = "GLFWtest"; @@ -56,13 +57,13 @@ fn main() { let mut lastFrame: f32 = 0.0; //gl::load_with(|ptr| window.get_proc_address(ptr) as *const _); - let gl = std::rc::Rc::new(glow::Context::from_loader_function(|s| window.get_proc_address(s) as *const _)); + let gl = std::rc::Rc::new(unsafe{glow::Context::from_loader_function(|s| window.get_proc_address(s) as *const _)}); let (ourshader, ourModel) = unsafe { - gl::Enable(gl::DEPTH_TEST); + gl.enable(glow::DEPTH_TEST); - let ourShader = shader::shader::new("model", gl); + let ourShader = shader::shader::new("model", Rc::clone(&gl)); - let ourModel = model::Model::new("resources/models/TestCarModel/CarW4.obj"); + let ourModel = model::Model::new("resources/models/TestCarModel/CarW4.obj", Rc::clone(&gl)); (ourShader, ourModel) }; @@ -72,7 +73,6 @@ fn main() { let projection: Matrix4 = perspective(Deg(45.0), SCR_WIDTH as f32/ SCR_HEIGHT as f32, 0.1, 100.0); println!("entering main loop"); - unsafe {gl::StencilOp(gl::KEEP, gl::KEEP, gl::REPLACE);} while !window.should_close() { let currentFrame = glfw.get_time() as f32; deltaTime = currentFrame - lastFrame; @@ -81,23 +81,23 @@ fn main() { processInput(&mut window, deltaTime, &mut camera); unsafe { - gl::Enable(gl::DEPTH_TEST); - gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT); + gl.enable(glow::DEPTH_TEST); + gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT); // outline ourshader.Use(); let Projection: Matrix4 = perspective(Deg(camera.Zoom), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 100.0); let view = camera.GetViewMatrix(); - ourshader.setMat4(&CString::new("projection").unwrap(), &projection); - ourshader.setMat4(&CString::new("view").unwrap(), &view); + ourshader.setMat4("projection", &projection); + ourshader.setMat4("view", &view); //let mut model = Matrix4::::from_translation(vec3(0.0, -0.3, 0.0)); let mut model: Matrix4 = Matrix4::from_axis_angle(vec3(0.0, -1.0, 0.0).normalize(), cgmath::Rad(glfw.get_time() as f32)); model = model * Matrix4::from_scale(0.2); - ourshader.setMat4(&CString::new("model").unwrap(), &model); + ourshader.setMat4("model", &model); ourModel.Draw(&ourshader); @@ -131,7 +131,7 @@ fn main() { } */ } - +/* fn process_events(events: &Receiver<(f64, glfw::WindowEvent)>, firstMouse: &mut bool, lastX: &mut f32, @@ -142,7 +142,7 @@ fn process_events(events: &Receiver<(f64, glfw::WindowEvent)>, glfw::WindowEvent::FramebufferSize(width, height) => { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. - unsafe { gl::Viewport(0, 0, width, height) } + unsafe { gl.viewport(0, 0, width, height) } } glfw::WindowEvent::CursorPos(xpos, ypos) => { let (xpos, ypos) = (xpos as f32, ypos as f32); @@ -167,3 +167,4 @@ fn process_events(events: &Receiver<(f64, glfw::WindowEvent)>, } } } +*/ diff --git a/src/model.rs b/src/model.rs index 321b695..128eaaa 100644 --- a/src/model.rs +++ b/src/model.rs @@ -3,10 +3,10 @@ use std::os::raw::c_void; use std::path::Path; - +use std::rc::Rc; use cgmath::{vec2, vec3}; -use gl; use image; +use glow::*; use image::DynamicImage::*; use image::GenericImage; use tobj; @@ -24,9 +24,9 @@ pub struct Model { impl Model { /// constructor, expects a filepath to a 3D model. - pub fn new(path: &str) -> Model { + pub fn new(path: &str, gl: std::rc::Rc) -> Model { let mut model = Model::default(); - model.loadModel(path); + model.loadModel(path, Rc::clone(&gl)); model } @@ -37,7 +37,7 @@ impl Model { } // loads a model from file and stores the resulting meshes in the meshes vector. - fn loadModel(&mut self, path: &str) { + fn loadModel(&mut self, path: &str, gl: std::rc::Rc) { let path = Path::new(path); // retrieve the directory path of the filepath @@ -53,9 +53,6 @@ impl Model { let mut vertices: Vec = Vec::with_capacity(num_vertices); let indices: Vec = mesh.indices.clone(); - println!("num vertices = {}", num_vertices); - println!("num normals = {}", &mesh.normals.len()); - println!("num TexCoords = {}", &mesh.texcoords.len()); let (p, n, t) = (&mesh.positions, &mesh.normals, &mesh.texcoords); for i in 0..num_vertices { vertices.push(Vertex { @@ -73,28 +70,28 @@ impl Model { // 1. diffuse map if !material.diffuse_texture.is_empty() { - let texture = self.loadMaterialTexture(&material.diffuse_texture, "texture_diffuse"); + let texture = self.loadMaterialTexture(&material.diffuse_texture, "texture_diffuse", Rc::clone(&gl)); textures.push(texture); } // 2. specular map if !material.specular_texture.is_empty() { - let texture = self.loadMaterialTexture(&material.specular_texture, "texture_specular"); + let texture = self.loadMaterialTexture(&material.specular_texture, "texture_specular", Rc::clone(&gl)); textures.push(texture); } // 3. normal map if !material.normal_texture.is_empty() { - let texture = self.loadMaterialTexture(&material.normal_texture, "texture_normal"); + let texture = self.loadMaterialTexture(&material.normal_texture, "texture_normal", Rc::clone(&gl)); textures.push(texture); } // NOTE: no height maps } - self.meshes.push(Mesh::new(vertices, indices, textures)); + self.meshes.push(Mesh::new(vertices, indices, textures, Rc::clone(&gl))); } } - fn loadMaterialTexture(&mut self, path: &str, typeName: &str) -> Texture { + fn loadMaterialTexture(&mut self, path: &str, typeName: &str, gl: Rc) -> Texture { { let texture = self.textures_loaded.iter().find(|t| t.path == path); if let Some(texture) = texture { @@ -103,7 +100,7 @@ impl Model { } let texture = Texture { - id: unsafe { TextureFromFile(path, &self.directory) }, + id: unsafe { TextureFromFile(path, &self.directory, std::rc::Rc::clone(&gl)) }, type_: typeName.into(), path: path.into() }; @@ -112,33 +109,31 @@ impl Model { } } -unsafe fn TextureFromFile(path: &str, directory: &str) -> u32 { +unsafe fn TextureFromFile(path: &str, directory: &str, gl: Rc) -> glow::NativeTexture { let filename = format!("{}/{}", directory, path); - let mut textureID = 0; - gl::GenTextures(1, &mut textureID); - + let mut textureID = gl.create_texture().unwrap(); let img = image::open(&Path::new(&filename)).expect("Texture failed to load"); let img = img.flipv(); let format = match img { - ImageLuma8(_) => gl::RED, - ImageLumaA8(_) => gl::RG, - ImageRgb8(_) => gl::RGB, - ImageRgba8(_) => gl::RGBA, + ImageLuma8(_) => glow::RED, + ImageLumaA8(_) => glow::RG, + ImageRgb8(_) => glow::RGB, + ImageRgba8(_) => glow::RGBA, _ => panic!("really weird image type"), }; let data = img.as_bytes(); - gl::BindTexture(gl::TEXTURE_2D, textureID); - gl::TexImage2D(gl::TEXTURE_2D, 0, format as i32, img.width() as i32, img.height() as i32, - 0, format, gl::UNSIGNED_BYTE, &data[0] as *const u8 as *const c_void); - gl::GenerateMipmap(gl::TEXTURE_2D); + gl.bind_texture(glow::TEXTURE_2D, Some(textureID)); + gl.tex_image_2d(glow::TEXTURE_2D, 0, format as i32, img.width() as i32, img.height() as i32, + 0, format, glow::UNSIGNED_BYTE, Some(&data)); + gl.generate_mipmap(glow::TEXTURE_2D); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR as i32); - gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32); + gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::REPEAT as i32); + gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, glow::REPEAT as i32); + gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::LINEAR_MIPMAP_LINEAR as i32); + gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::LINEAR as i32); textureID } diff --git a/src/model/mesh.rs b/src/model/mesh.rs index a94421c..c0bc897 100644 --- a/src/model/mesh.rs +++ b/src/model/mesh.rs @@ -8,7 +8,7 @@ use std::ptr; use cgmath::{ Vector3, Vector2 }; use cgmath::prelude::*; -use gl; +use glow::*; use field_offset::offset_of; use crate::shader::shader; @@ -43,7 +43,7 @@ impl Default for Vertex { #[derive(Clone)] pub struct Texture { - pub id: u32, + pub id: glow::NativeTexture, pub type_: String, pub path: String, } @@ -53,22 +53,28 @@ pub struct Mesh { pub vertices: Vec, pub indices: Vec, pub textures: Vec, - pub VAO: u32, + pub VAO: glow::VertexArray, /* Render data */ - VBO: u32, - EBO: u32, + VBO: glow::Buffer, + EBO: glow::Buffer, } impl Mesh { - pub fn new(vertices: Vec, indices: Vec, textures: Vec) -> Mesh { + pub fn new(vertices: Vec, indices: Vec, textures: Vec,gl: std::rc::Rc) -> Mesh { + + let mut mesh = + { + unsafe { let mut mesh = Mesh { vertices, indices, textures, - VAO: 0, VBO: 0, EBO: 0 + VAO: gl.create_vertex_array().unwrap(), VBO: gl.create_buffer().unwrap(), EBO: gl.create_buffer().unwrap() }; - + mesh + } + }; // now that we have all the required data, set the vertex buffers and its attribute pointers. - unsafe { mesh.setupMesh() } + unsafe { mesh.setupMesh(gl) } mesh } @@ -80,7 +86,7 @@ impl Mesh { let mut normalNr = 0; let mut heightNr = 0; for (i, texture) in self.textures.iter().enumerate() { - gl::ActiveTexture(gl::TEXTURE0 + i as u32); // active proper texture unit before binding + shader.gl.active_texture(glow::TEXTURE0 + i as u32); // active proper texture unit before binding // retrieve texture number (the N in diffuse_textureN) let name = &texture.type_; let number = match name.as_str() { @@ -103,60 +109,66 @@ impl Mesh { _ => panic!("unknown texture type") }; // now set the sampler to the correct texture unit - let sampler = CString::new(format!("{}{}", name, number)).unwrap(); - gl::Uniform1i(gl::GetUniformLocation(shader.ID, sampler.as_ptr()), i as i32); + let sampler = String::from(format!("{}{}", name, number)); + shader.setInt(&sampler, i as i32); // and finally bind the texture - gl::BindTexture(gl::TEXTURE_2D, texture.id); + shader.gl.bind_texture(glow::TEXTURE_2D, Some(texture.id)); } // draw mesh - gl::BindVertexArray(self.VAO); - gl::DrawElements(gl::TRIANGLES, self.indices.len() as i32, gl::UNSIGNED_INT, ptr::null()); - gl::BindVertexArray(0); + shader.gl.bind_vertex_array(Some(self.VAO)); + shader.gl.draw_elements(glow::TRIANGLES, self.indices.len() as i32, glow::UNSIGNED_INT, 0); + shader.gl.bind_vertex_array(None); // always good practice to set everything back to defaults once configured. - gl::ActiveTexture(gl::TEXTURE0); + shader.gl.active_texture(glow::TEXTURE0); } - unsafe fn setupMesh(&mut self) { + unsafe fn setupMesh(&mut self, gl: std::rc::Rc) { // create buffers/arrays - gl::GenVertexArrays(1, &mut self.VAO); - gl::GenBuffers(1, &mut self.VBO); - gl::GenBuffers(1, &mut self.EBO); - - gl::BindVertexArray(self.VAO); + gl.bind_vertex_array(Some(self.VAO)); // load data into vertex buffers - gl::BindBuffer(gl::ARRAY_BUFFER, self.VBO); + gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.VBO)); // A great thing about structs with repr(C) is that their memory layout is sequential for all its items. // The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which // again translates to 3/2 floats which translates to a byte array. - let size = (self.vertices.len() * size_of::()) as isize; - let data = &self.vertices[0] as *const Vertex as *const c_void; - gl::BufferData(gl::ARRAY_BUFFER, size, data, gl::STATIC_DRAW); + //let size = (self.vertices.len() * size_of::()) as isize; + //let data = &self.vertices[0] as *const Vertex as *const c_void; + let data: &[u8] = core::slice::from_raw_parts( + self.vertices.as_ptr() as *const u8, + self.vertices.len() * core::mem::size_of::(), + ); - gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.EBO); - let size = (self.indices.len() * size_of::()) as isize; - let data = &self.indices[0] as *const u32 as *const c_void; - gl::BufferData(gl::ELEMENT_ARRAY_BUFFER, size, data, gl::STATIC_DRAW); + + + + gl.buffer_data_u8_slice(glow::ARRAY_BUFFER, data, glow::STATIC_DRAW); + + gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.EBO)); + let data: &[u8] = core::slice::from_raw_parts( + self.indices.as_ptr() as *const u8, + self.indices.len() * core::mem::size_of::(), + ); + gl.buffer_data_u8_slice(glow::ELEMENT_ARRAY_BUFFER, data, glow::STATIC_DRAW); // set the vertex attribute pointers let size = size_of::() as i32; // vertex Positions - gl::EnableVertexAttribArray(0); - gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex => Position).get_byte_offset() as *const c_void); + gl.enable_vertex_attrib_array(0); + gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, size, offset_of!(Vertex => Position).get_byte_offset() as i32); // vertex normals - gl::EnableVertexAttribArray(1); - gl::VertexAttribPointer(1, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex => Normal).get_byte_offset() as *const c_void); + gl.enable_vertex_attrib_array(1); + gl.vertex_attrib_pointer_f32(1, 3, glow::FLOAT, false, size, offset_of!(Vertex => Normal).get_byte_offset() as i32); // vertex texture coords - gl::EnableVertexAttribArray(2); - gl::VertexAttribPointer(2, 2, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex => TexCoords).get_byte_offset() as *const c_void); + gl.enable_vertex_attrib_array(2); + gl.vertex_attrib_pointer_f32(2, 2, glow::FLOAT, false, size, offset_of!(Vertex => TexCoords).get_byte_offset() as i32); // vertex tangent - gl::EnableVertexAttribArray(3); - gl::VertexAttribPointer(3, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex => Tangent).get_byte_offset() as *const c_void); + gl.enable_vertex_attrib_array(3); + gl.vertex_attrib_pointer_f32(3, 3, glow::FLOAT, false, size, offset_of!(Vertex => Tangent).get_byte_offset() as i32); // vertex bitangent - gl::EnableVertexAttribArray(4); - gl::VertexAttribPointer(4, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex => Bitangent).get_byte_offset() as *const c_void); + gl.enable_vertex_attrib_array(4); + gl.vertex_attrib_pointer_f32(4, 3, glow::FLOAT, false, size, offset_of!(Vertex => Bitangent).get_byte_offset() as i32); - gl::BindVertexArray(0); + gl.bind_vertex_array(None); } } diff --git a/src/shader.rs b/src/shader.rs index b5e9b40..9f066bc 100644 --- a/src/shader.rs +++ b/src/shader.rs @@ -1,16 +1,14 @@ use glow::*; use std::fs; -use std::ffi::{CString, CStr}; use std::rc::Rc; use std::str; -use cgmath::prelude::*; /// Shader Struct for creating and using shaders in the Context of engine /// pub struct shader { pub ID: NativeProgram, - gl: Rc + pub gl: Rc } @@ -61,7 +59,7 @@ use cgmath::prelude::*; shader { ID: shader_program, gl: Rc::clone(&gl), - }; + } } } @@ -70,9 +68,9 @@ use cgmath::prelude::*; // return program /// uses Shader - pub fn Use(&self, gl: glow::Context) + pub fn Use(&self) { - unsafe {gl.use_program(Some(self.ID));} + unsafe {self.gl.use_program(Some(self.ID));} } // BOILERPLATE JUMPSCARE