From 57d4ecb18a714f5ded3cef2306441d26250d898a Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Thu, 2 Nov 2023 03:38:14 +0200 Subject: [PATCH] feat: basic texture support - add texture support (ambient, diffuse, specular) - use opacity in fragment shader - calculate normal matrix on cpu for matricies with big determinants --- shaders/frag.glsl | 96 +++++++++++++++++++---------------------- shaders/vertex.glsl | 6 ++- src/importer/mod.rs | 53 +++++++++++++++++++---- src/importer/obj.rs | 42 ++++++++++++++---- src/main.rs | 2 +- src/mesh.rs | 102 ++++++++++++++++++++------------------------ src/model.rs | 53 +---------------------- src/ui/ui.rs | 4 ++ src/utils.rs | 13 ++++-- 9 files changed, 190 insertions(+), 181 deletions(-) diff --git a/shaders/frag.glsl b/shaders/frag.glsl index 0e9604f..cae6e29 100644 --- a/shaders/frag.glsl +++ b/shaders/frag.glsl @@ -6,43 +6,15 @@ in vec2 texCoords; out vec4 FragColor; struct Material { - sampler2D texture_diffuse1; - sampler2D texture_diffuse2; - sampler2D texture_diffuse3; - sampler2D texture_diffuse4; - sampler2D texture_diffuse5; - sampler2D texture_diffuse6; - sampler2D texture_diffuse7; - sampler2D texture_diffuse8; - sampler2D texture_diffuse9; - sampler2D texture_diffuse10; - sampler2D texture_diffuse11; - sampler2D texture_diffuse12; - sampler2D texture_diffuse13; - sampler2D texture_diffuse14; - sampler2D texture_diffuse15; - sampler2D texture_diffuse16; - sampler2D texture_specular1; - sampler2D texture_specular2; - sampler2D texture_specular3; - sampler2D texture_specular4; - sampler2D texture_specular5; - sampler2D texture_specular6; - sampler2D texture_specular7; - sampler2D texture_specular8; - sampler2D texture_specular9; - sampler2D texture_specular10; - sampler2D texture_specular11; - sampler2D texture_specular12; - sampler2D texture_specular13; - sampler2D texture_specular14; - sampler2D texture_specular15; - sampler2D texture_specular16; + sampler2D texture_diffuse; + sampler2D texture_specular; + sampler2D texture_ambient; vec3 ambient; vec3 diffuse; vec3 specular; float shininess; + float opacity; }; struct DirLight { @@ -88,6 +60,7 @@ uniform Material material; uniform DirLight dirLight; uniform PointLight pointLights[NR_POINT_LIGHTS]; uniform SpotLight spotLight; +uniform bool useTextures; vec3 CalculateDirLight(DirLight light, vec3 normal, vec3 viewDir) { vec3 lightDir = normalize(-light.direction); @@ -103,12 +76,19 @@ vec3 CalculateDirLight(DirLight light, vec3 normal, vec3 viewDir) { spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); } - //vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, texCoords)) * material.ambient; - //vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, texCoords)) * material.diffuse; - //vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, texCoords)) * material.specular; - vec3 ambient = light.ambient * material.ambient; - vec3 diffuse = light.diffuse * (diff * material.diffuse); - vec3 specular = light.specular * (spec * material.specular); + vec3 ambient = vec3(0.0, 0.0, 0.0); + vec3 diffuse = vec3(0.0, 0.0, 0.0); + vec3 specular = vec3(0.0, 0.0, 0.0); + + if (useTextures) { + ambient = light.ambient * vec3(texture(material.texture_ambient, texCoords)) * material.ambient; + diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse, texCoords)) * material.diffuse; + specular = light.specular * spec * vec3(texture(material.texture_specular, texCoords)) * material.specular; + } else { + ambient = light.ambient * material.ambient; + diffuse = light.diffuse * (diff * material.diffuse); + specular = light.specular * (spec * material.specular); + } return (ambient + diffuse + specular); } @@ -131,12 +111,19 @@ vec3 CalculatePointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewD float distance = length(light.position - fragPos); float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance + distance)); - //vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, texCoords)) * material.ambient; - //vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, texCoords)) * material.diffuse; - //vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, texCoords)) * material.specular; - vec3 ambient = light.ambient * material.ambient; - vec3 diffuse = light.diffuse * (diff * material.diffuse); - vec3 specular = light.specular * (spec * material.specular); + vec3 ambient = vec3(0.0, 0.0, 0.0); + vec3 diffuse = vec3(0.0, 0.0, 0.0); + vec3 specular = vec3(0.0, 0.0, 0.0); + + if (useTextures) { + ambient = light.ambient * vec3(texture(material.texture_ambient, texCoords)) * material.ambient; + diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse, texCoords)) * material.diffuse; + specular = light.specular * spec * vec3(texture(material.texture_specular, texCoords)) * material.specular; + } else { + ambient = light.ambient * material.ambient; + diffuse = light.diffuse * (diff * material.diffuse); + specular = light.specular * (spec * material.specular); + } ambient *= attenuation; diffuse *= attenuation; @@ -168,12 +155,19 @@ vec3 CalculateSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir float epsilon = light.cutOff - light.outerCutOff; float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); - //vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, texCoords)) * material.ambient; - //vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, texCoords)) * material.diffuse; - //vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, texCoords)) * material.specular; - vec3 ambient = light.ambient * material.ambient; - vec3 diffuse = light.diffuse * (diff * material.diffuse); - vec3 specular = light.specular * (spec * material.specular); + vec3 ambient = vec3(0.0, 0.0, 0.0); + vec3 diffuse = vec3(0.0, 0.0, 0.0); + vec3 specular = vec3(0.0, 0.0, 0.0); + + if (useTextures) { + ambient = light.ambient * vec3(texture(material.texture_ambient, texCoords)) * material.ambient; + diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse, texCoords)) * material.diffuse; + specular = light.specular * spec * vec3(texture(material.texture_specular, texCoords)) * material.specular; + } else { + ambient = light.ambient * material.ambient; + diffuse = light.diffuse * (diff * material.diffuse); + specular = light.specular * (spec * material.specular); + } diffuse *= intensity; specular *= intensity; @@ -200,6 +194,6 @@ void main() result += CalculateSpotLight(spotLight, norm, fragPos, viewDir); - FragColor = vec4(result, 1.0); + FragColor = vec4(result, material.opacity); } diff --git a/shaders/vertex.glsl b/shaders/vertex.glsl index 9647c77..32c34f7 100644 --- a/shaders/vertex.glsl +++ b/shaders/vertex.glsl @@ -10,11 +10,15 @@ uniform mat4 model; uniform mat4 view; uniform mat4 projection; uniform mat3 normalMatrix; +uniform bool useNormalMatrix; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0f); - fragNormals = normalMatrix * aNormal; + if (useNormalMatrix) + fragNormals = normalMatrix * aNormal; + else + fragNormals = mat3(transpose(inverse(model))) * aNormal; fragPos = vec3(model * vec4(aPos, 1.0)); texCoords = aTexCoords; } diff --git a/src/importer/mod.rs b/src/importer/mod.rs index 9e8b5dc..a11fce2 100644 --- a/src/importer/mod.rs +++ b/src/importer/mod.rs @@ -1,9 +1,9 @@ mod obj; mod stl; -use std::{path::PathBuf, collections::HashMap}; +use std::path::PathBuf; -use crate::{mesh::Vertex, aabb::AABB, utils::SupportedFileExtensions}; +use crate::{mesh::Vertex, aabb::AABB, utils::{SupportedFileExtensions, self}}; #[derive(Debug, Clone)] pub enum TextureType { @@ -18,7 +18,23 @@ pub enum TextureType { Emissive } -// TODO: take the textures out of the material and put it on the model/object +impl TextureType { + pub fn from_material_str(token: &str) -> Option { + match token { + "map_Ka" => Some(TextureType::Ambient), + "map_Kd" => Some(TextureType::Diffuse), + "map_Ks" => Some(TextureType::Specular), + "map_Ns" => Some(TextureType::SpecularHighlight), + "map_bump" => Some(TextureType::Bump), + "map_d" => Some(TextureType::Displacement), + "decal" => Some(TextureType::Decal), + "refl" => Some(TextureType::Reflection), + "map_Ke" => Some(TextureType::Emissive), + _ => None + } + } +} + #[derive(Debug, Clone)] pub struct Material { pub name: String, @@ -27,11 +43,11 @@ pub struct Material { pub specular_color: glm::Vec3, pub specular_exponent: f32, pub opacity: f32, - pub textures: HashMap, + pub textures: Vec } impl Material { - fn new(name: String, ambient: glm::Vec3, diffuse: glm::Vec3, specular: glm::Vec3, shininess: f32, opacity: f32, textures: HashMap) -> Self { + fn new(name: String, ambient: glm::Vec3, diffuse: glm::Vec3, specular: glm::Vec3, shininess: f32, opacity: f32, textures: Vec) -> Self { Self { name, ambient_color: ambient, @@ -53,7 +69,7 @@ impl Default for Material { specular_color: glm::vec3(0.1, 0.1, 0.1), specular_exponent: 32.0, opacity: 1.0, - textures: HashMap::new() + textures: Vec::new() } } } @@ -62,16 +78,35 @@ impl std::fmt::Display for Material { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!( f, - "Ambient: {:?}\nDiffuse: {:?}\nSpecular: {:?}\nShininess: {}\nOpacity: {}", + "Ambient: {:?}\nDiffuse: {:?}\nSpecular: {:?}\nShininess: {}\nOpacity: {}\nTextures: {:?}", self.ambient_color, self.diffuse_color, self.specular_color, self.specular_exponent, - self.opacity + self.opacity, + self.textures ) } } +#[derive(Clone, Debug)] +pub struct Texture { + pub id: u32, + pub typ: TextureType, +} + +impl Texture { + pub fn new(path: std::path::PathBuf, typ: TextureType) -> Result> { + let id = utils::load_texture(path)?; + + Ok(Texture { + id, + typ, + }) + } +} + + #[derive(Debug)] pub struct ObjMesh { pub name: String, @@ -84,7 +119,7 @@ pub struct ObjMesh { pub struct Object { pub name: String, pub meshes: Vec, - pub aabb: AABB + pub aabb: AABB, } pub fn load_from_file(path: &PathBuf) -> Result> { diff --git a/src/importer/obj.rs b/src/importer/obj.rs index 83e95a6..a762a0b 100644 --- a/src/importer/obj.rs +++ b/src/importer/obj.rs @@ -2,7 +2,7 @@ use std::{io::{BufReader, BufRead}, collections::HashMap, path::PathBuf}; use log::{error, warn, trace}; -use crate::{mesh::Vertex, aabb::AABB, importer::ObjMesh, importer::Object, importer::Material}; +use crate::{mesh::Vertex, aabb::AABB, importer::{ObjMesh, Object, Material, Texture, TextureType}}; const BUF_CAP: usize = 1024 * 128; // 128 Kilobytes @@ -84,7 +84,7 @@ impl MtlToken { } } -fn parse_mtl(path: &PathBuf) -> Result, Box> { +fn parse_mtl(path: &PathBuf, obj_textures: &mut HashMap) -> Result, Box> { let file = std::fs::File::open(path)?; let reader = BufReader::with_capacity(BUF_CAP, file); let mut material_name = String::new(); @@ -95,6 +95,7 @@ fn parse_mtl(path: &PathBuf) -> Result, Box = Vec::new(); for line in reader.lines() { let line = line?; @@ -109,8 +110,10 @@ fn parse_mtl(path: &PathBuf) -> Result, Box { if !material_name.is_empty() { - material = Material::new(material_name.clone(), ambient, diffuse, specular, shininess, opacity, HashMap::new()); + material = Material::new(material_name.clone(), ambient, diffuse, specular, shininess, opacity, mat_textures.clone()); materials.insert(material_name, material); + + mat_textures.clear(); } material_name = iter.next().unwrap().to_string(); @@ -139,15 +142,36 @@ fn parse_mtl(path: &PathBuf) -> Result, Box { opacity = iter.next().unwrap().parse::().unwrap(); } - Some(MtlToken::DiffuseTexture) => { - // TODO: textures + Some(MtlToken::DiffuseTexture) + | Some(MtlToken::AmbientTexture) + | Some(MtlToken::SpecularTexture) => { + let tex_type = TextureType::from_material_str(token).unwrap(); + + let name = iter.next().unwrap().to_string(); + let mat = if obj_textures.contains_key(&name) { + obj_textures.get(&name).unwrap().clone() + } else { + let path = path.parent().unwrap().join(&name); + let tex = match Texture::new(path, tex_type) { + Ok(v) => v, + Err(e) => { + error!("Failed to load texture: {}", e); + continue; + } + }; + + obj_textures.insert(name, tex.clone()); + tex + }; + + mat_textures.push(mat); } _ => { warn!("Unhandled material token: {}", token) }, } } } - material = Material::new(material_name.clone(), ambient, diffuse, specular, shininess, opacity, HashMap::new()); + material = Material::new(material_name.clone(), ambient, diffuse, specular, shininess, opacity, mat_textures); materials.insert(material_name, material); @@ -170,6 +194,7 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result = None; let mut min_aabb = glm::vec3(f32::MAX, f32::MAX, f32::MAX); let mut max_aabb = glm::vec3(f32::MIN, f32::MIN, f32::MIN); + let mut textures = HashMap::new(); for line in reader.lines() { let line = line?; @@ -264,7 +289,8 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result().unwrap()); let u = iter.next().unwrap(); let v = iter.next().unwrap(); - tex_coords.push(glm::vec2(u, v)); + // vertically flip the texcoords because flipping the texture is expensive + tex_coords.push(glm::vec2(u, 1.0 - v)); } Some(ObjToken::Face) => { let face = iter.collect::>(); @@ -372,7 +398,7 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result { for matlib in iter { let material_path = obj_path.parent().unwrap().join(matlib); - let new_materials = parse_mtl(&material_path); + let new_materials = parse_mtl(&material_path, &mut textures); match new_materials { Ok(m) => { materials.extend(m); diff --git a/src/main.rs b/src/main.rs index dba904b..002d12e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -264,7 +264,7 @@ fn main() -> anyhow::Result<(), Box> { } else { gl::PolygonMode(gl::FRONT_AND_BACK, gl::FILL); } - if Some(obj.id) == state.active_model {obj.draw(&mesh_shader, state.draw_aabb);} + if Some(obj.id) == state.active_model {obj.draw(&mesh_shader, state.draw_aabb, state.show_textures);} } gl::PolygonMode(gl::FRONT_AND_BACK, gl::FILL); diff --git a/src/mesh.rs b/src/mesh.rs index 3d1d7d1..dcf7564 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -1,6 +1,7 @@ use glad_gl::gl; +use log::warn; -use crate::{shader::Shader, utils, importer::Material}; +use crate::{shader::Shader, utils, importer::{Material, TextureType}}; fn create_rotation_matrix(pitch: f32, yaw: f32, roll: f32, pivot: glm::Vec3) -> glm::Mat4 { let pitch = pitch.to_radians(); @@ -36,7 +37,6 @@ pub struct Mesh { pub vertices: Vec, pub indices: Vec, - // pub textures: Vec, pub material: Material, vao: u32, @@ -82,7 +82,6 @@ impl Mesh { name: name.to_string(), vertices, indices, - // textures, material: material.unwrap_or_default(), vbo, vao, @@ -94,23 +93,26 @@ impl Mesh { } } - pub fn draw(&self, shader: &Shader, scale: f32, pivot: glm::Vec3) { - // let mut diffuse = 1; - // let mut specular = 1; - + pub fn draw(&self, shader: &Shader, scale: f32, pivot: glm::Vec3, show_textures: bool) { shader.use_shader(); let model_mat = glm::ext::scale(&utils::mat_ident(), glm::vec3(scale, scale, scale)); let model_mat = apply_rotation(&model_mat, self.rotation, pivot); let model_mat = glm::ext::translate(&model_mat, glm::vec3(self.position.x, self.position.y, self.position.z)); shader.set_mat4fv("model", &model_mat); - let normal_mat = glm::transpose(&glm::inverse(&model_mat)); - let normal_mat = glm::mat3( - normal_mat[0][0], normal_mat[0][1], normal_mat[0][2], - normal_mat[1][0], normal_mat[1][1], normal_mat[1][2], - normal_mat[2][0], normal_mat[2][1], normal_mat[2][2], - ); - shader.set_mat3fv("normalMatrix", &normal_mat); + + if glm::ext::is_invertible(&model_mat) { + let normal_mat = glm::transpose(&glm::inverse(&model_mat)); + let normal_mat = glm::mat3( + normal_mat[0][0], normal_mat[0][1], normal_mat[0][2], + normal_mat[1][0], normal_mat[1][1], normal_mat[1][2], + normal_mat[2][0], normal_mat[2][1], normal_mat[2][2], + ); + shader.set_mat3fv("normalMatrix", &normal_mat); + shader.set_bool("useNormalMatrix", true); + } else { + shader.set_bool("useNormalMatrix", false); + } let mut polygon_mode = 0; unsafe { @@ -119,34 +121,44 @@ impl Mesh { let is_wireframe = polygon_mode as u32 == gl::LINE; if !is_wireframe { + // TODO: these can be missing in the (.obj) material, maybe we should set them + // to 1.0 as fallback. shininess too shader.set_3fv("material.ambient", self.material.ambient_color); shader.set_3fv("material.diffuse", self.material.diffuse_color); shader.set_3fv("material.specular", self.material.specular_color); - shader.set_float("material.shininess", self.material.specular_exponent); + shader.set_float("material.shininess", 32.0); + shader.set_float("material.opacity", self.material.opacity); } else { shader.set_3fv("material.ambient", glm::vec3(0.0, 0.0, 0.0)); shader.set_3fv("material.diffuse", glm::vec3(0.0, 0.0, 0.0)); } - // for i in 0..self.textures.len() { - // unsafe { - // gl::ActiveTexture(gl::TEXTURE0 + i as u32); - // match self.textures[i].typ { - // russimp::material::TextureType::Diffuse => { - // diffuse += 1; - // shader.set_int(format!("material.texture_diffuse{}", diffuse).as_str(), i as i32); - // }, - // russimp::material::TextureType::Specular => { - // specular += 1; - // shader.set_int(format!("material.texture_specular{}", specular).as_str(), i as i32); - // }, - // _ => {}, // don't do anything because unsupported texture types are logged - // // when the model is loaded - // } + if show_textures { + shader.set_bool("useTextures", self.material.textures.len() > 0); + for (i, tex) in self.material.textures.iter().enumerate() { + unsafe { + gl::ActiveTexture(gl::TEXTURE0 + i as u32); + match tex.typ { + TextureType::Ambient => { + shader.set_int("material.texture_ambient", i as i32); + }, + TextureType::Diffuse => { + shader.set_int("material.texture_diffuse", i as i32); + }, + TextureType::Specular => { + shader.set_int("material.texture_specular{}", i as i32); + }, + _ => { + warn!("Unsupported texture type: {:?}", tex.typ); + }, + } - // gl::BindTexture(gl::TEXTURE_2D, self.textures[i].id); - // } - // } + gl::BindTexture(gl::TEXTURE_2D, tex.id); + } + } + } else { + shader.set_bool("useTextures", false); + } unsafe { // draw Mesh @@ -170,6 +182,7 @@ impl Mesh { impl Drop for Mesh { fn drop(&mut self) { + // TODO: should we impl a Drop on material to delete the textures from gpu?? unsafe { gl::BindVertexArray(0); gl::DeleteBuffers(1, &self.vbo); @@ -197,26 +210,3 @@ impl Vertex { } } -// #[derive(Clone, Debug)] -// pub struct Texture { -// pub id: u32, -// pub typ: russimp::material::TextureType, -// pub path: std::path::PathBuf, -// } - -// impl Texture { -// pub fn new(path: std::path::PathBuf, typ: russimp::material::TextureType) -> Result> { -// let path_str = match path.to_str() { -// Some(path) => path, -// None => return Err("Failed to convert texture path to string".into()), -// }; -// let id = utils::load_texture(path_str)?; - -// Ok(Texture { -// id, -// typ, -// path, -// }) -// } -// } - diff --git a/src/model.rs b/src/model.rs index 1124177..4ce673f 100644 --- a/src/model.rs +++ b/src/model.rs @@ -12,55 +12,6 @@ pub struct Model { pub mem_usage: usize, } -// TODO: texture support, kept for reference -// fn load_material_textures( -// mat: &russimp::material::Material, -// dir: &std::path::PathBuf, -// loaded_textures: &mut Vec -// ) -> (Vec, Vec>) { - -// let mut textures = vec![]; -// let mut errors = vec![]; - -// for (typ, tex) in mat.textures.iter() { -// if SUPPORTED_TEXTURE_TYPES.contains(typ) { -// let texture = tex.borrow(); -// let mut skip = false; -// let tex_filename = &texture.filename; -// // HACK: fix this -// if tex_filename.is_empty() { -// continue; -// } -// // println!("texture filename: {}", tex_filename); -// let path = dir.join(tex_filename); - -// for loaded_tex in &mut *loaded_textures { -// if loaded_tex.path == path { -// textures.push(loaded_tex.clone()); -// skip = true; -// break; -// } -// } - -// if !skip { -// match Texture::new(path, *typ) { -// Ok(texture) => { -// loaded_textures.push(texture.clone()); -// textures.push(texture); -// }, -// Err(e) => { -// let err = anyhow!("Error loading texture: {}", e); -// println!("{}", err); -// errors.push(err.into()); -// }, -// } -// } -// } -// } - -// return (textures, errors); -// } - impl Model { pub fn new(obj: importer::Object, state: &mut ui::State) -> Model { let mut meshes = Vec::new(); @@ -90,7 +41,7 @@ impl Model { return model; } - pub fn draw(&self, shader: &Shader, draw_aabb: bool) { + pub fn draw(&self, shader: &Shader, draw_aabb: bool, show_textures: bool) { let center_x = ((self.aabb.max.x / 2.0) + (self.aabb.min.x / 2.0)) * self.scaling_factor; let center_y = ((self.aabb.max.y / 2.0) + (self.aabb.min.y / 2.0)) * self.scaling_factor; let center_z = ((self.aabb.max.z / 2.0) + (self.aabb.min.z / 2.0)) * self.scaling_factor; @@ -102,7 +53,7 @@ impl Model { for mesh in &self.meshes { - mesh.draw(shader, self.scaling_factor, pivot); + mesh.draw(shader, self.scaling_factor, pivot, show_textures); } if draw_aabb { diff --git a/src/ui/ui.rs b/src/ui/ui.rs index fbbe06b..3e582b9 100644 --- a/src/ui/ui.rs +++ b/src/ui/ui.rs @@ -31,6 +31,7 @@ pub struct State { pub logger: logger::WritableLog, pub settings: Settings, pub fps: f32, + pub show_textures: bool } impl Default for State { @@ -55,6 +56,7 @@ impl Default for State { logger: logger::WritableLog::default(), settings: Settings::default(), fps: 0.0, + show_textures: true } } } @@ -487,6 +489,8 @@ fn draw_viewport(ui: &imgui::Ui, state: &mut State, texture: u32) { ui.same_line(); ui.checkbox("FOV zoom", &mut state.fov_zoom); ui.same_line(); + ui.checkbox("Show Textures", &mut state.show_textures); + ui.same_line(); ui.set_next_item_width(150.0); imgui::Drag::new("Camera Speed") .range(1.0, 10000.0) diff --git a/src/utils.rs b/src/utils.rs index 7c7c382..fb03f7e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -22,11 +22,11 @@ impl SupportedFileExtensions { } } -pub fn load_texture(path: &str) -> Result { - let tex = image::io::Reader::open(path) - .with_context(|| format!("Failed to open texture file: {}", path))? +pub fn load_texture(path: PathBuf) -> Result { + let tex = image::io::Reader::open(path.clone()) + .with_context(|| format!("Failed to open texture file: {:?}", path))? .decode() - .with_context(|| format!("Failed to decode texture: {}", path))?; + .with_context(|| format!("Failed to decode texture: {:?}", path))?; let mut texture_id: u32 = 0; let format = match tex.color().channel_count() { @@ -38,6 +38,9 @@ pub fn load_texture(path: &str) -> Result { }; unsafe { + // set alignment to 1 since we use u8 for the pixel data type + gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1); + gl::GenTextures(1, &mut texture_id); gl::BindTexture(gl::TEXTURE_2D, texture_id); @@ -49,6 +52,8 @@ pub fn load_texture(path: &str) -> Result { gl::TexImage2D(gl::TEXTURE_2D, 0, format as i32, tex.width() as i32, tex.height() as i32, 0, format, gl::UNSIGNED_BYTE, tex.as_bytes().as_ptr() as *const std::ffi::c_void); gl::GenerateMipmap(gl::TEXTURE_2D); + + gl::PixelStorei(gl::UNPACK_ALIGNMENT, 4); } Ok(texture_id)