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
This commit is contained in:
2023-11-02 04:15:59 +02:00
committed by Illusion
parent 4b15990703
commit 08659a0a78
9 changed files with 190 additions and 181 deletions
+45 -51
View File
@@ -6,43 +6,15 @@ in vec2 texCoords;
out vec4 FragColor; out vec4 FragColor;
struct Material { struct Material {
sampler2D texture_diffuse1; sampler2D texture_diffuse;
sampler2D texture_diffuse2; sampler2D texture_specular;
sampler2D texture_diffuse3; sampler2D texture_ambient;
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;
vec3 ambient; vec3 ambient;
vec3 diffuse; vec3 diffuse;
vec3 specular; vec3 specular;
float shininess; float shininess;
float opacity;
}; };
struct DirLight { struct DirLight {
@@ -88,6 +60,7 @@ uniform Material material;
uniform DirLight dirLight; uniform DirLight dirLight;
uniform PointLight pointLights[NR_POINT_LIGHTS]; uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform SpotLight spotLight; uniform SpotLight spotLight;
uniform bool useTextures;
vec3 CalculateDirLight(DirLight light, vec3 normal, vec3 viewDir) { vec3 CalculateDirLight(DirLight light, vec3 normal, vec3 viewDir) {
vec3 lightDir = normalize(-light.direction); 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); spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
} }
//vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, texCoords)) * material.ambient; vec3 ambient = vec3(0.0, 0.0, 0.0);
//vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, texCoords)) * material.diffuse; vec3 diffuse = vec3(0.0, 0.0, 0.0);
//vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, texCoords)) * material.specular; vec3 specular = vec3(0.0, 0.0, 0.0);
vec3 ambient = light.ambient * material.ambient;
vec3 diffuse = light.diffuse * (diff * material.diffuse); if (useTextures) {
vec3 specular = light.specular * (spec * material.specular); 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); 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 distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance + distance)); 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 ambient = vec3(0.0, 0.0, 0.0);
//vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, texCoords)) * material.diffuse; vec3 diffuse = vec3(0.0, 0.0, 0.0);
//vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, texCoords)) * material.specular; vec3 specular = vec3(0.0, 0.0, 0.0);
vec3 ambient = light.ambient * material.ambient;
vec3 diffuse = light.diffuse * (diff * material.diffuse); if (useTextures) {
vec3 specular = light.specular * (spec * material.specular); 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; ambient *= attenuation;
diffuse *= attenuation; diffuse *= attenuation;
@@ -168,12 +155,19 @@ vec3 CalculateSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir
float epsilon = light.cutOff - light.outerCutOff; float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
//vec3 ambient = light.ambient * vec3(texture(material.texture_diffuse1, texCoords)) * material.ambient; vec3 ambient = vec3(0.0, 0.0, 0.0);
//vec3 diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse1, texCoords)) * material.diffuse; vec3 diffuse = vec3(0.0, 0.0, 0.0);
//vec3 specular = light.specular * spec * vec3(texture(material.texture_specular1, texCoords)) * material.specular; vec3 specular = vec3(0.0, 0.0, 0.0);
vec3 ambient = light.ambient * material.ambient;
vec3 diffuse = light.diffuse * (diff * material.diffuse); if (useTextures) {
vec3 specular = light.specular * (spec * material.specular); 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; diffuse *= intensity;
specular *= intensity; specular *= intensity;
@@ -200,6 +194,6 @@ void main()
result += CalculateSpotLight(spotLight, norm, fragPos, viewDir); result += CalculateSpotLight(spotLight, norm, fragPos, viewDir);
FragColor = vec4(result, 1.0); FragColor = vec4(result, material.opacity);
} }
+4
View File
@@ -10,11 +10,15 @@ uniform mat4 model;
uniform mat4 view; uniform mat4 view;
uniform mat4 projection; uniform mat4 projection;
uniform mat3 normalMatrix; uniform mat3 normalMatrix;
uniform bool useNormalMatrix;
void main() void main()
{ {
gl_Position = projection * view * model * vec4(aPos, 1.0f); gl_Position = projection * view * model * vec4(aPos, 1.0f);
if (useNormalMatrix)
fragNormals = normalMatrix * aNormal; fragNormals = normalMatrix * aNormal;
else
fragNormals = mat3(transpose(inverse(model))) * aNormal;
fragPos = vec3(model * vec4(aPos, 1.0)); fragPos = vec3(model * vec4(aPos, 1.0));
texCoords = aTexCoords; texCoords = aTexCoords;
} }
+44 -9
View File
@@ -1,9 +1,9 @@
mod obj; mod obj;
mod stl; 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)] #[derive(Debug, Clone)]
pub enum TextureType { pub enum TextureType {
@@ -18,7 +18,23 @@ pub enum TextureType {
Emissive 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<Self> {
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)] #[derive(Debug, Clone)]
pub struct Material { pub struct Material {
pub name: String, pub name: String,
@@ -27,11 +43,11 @@ pub struct Material {
pub specular_color: glm::Vec3, pub specular_color: glm::Vec3,
pub specular_exponent: f32, pub specular_exponent: f32,
pub opacity: f32, pub opacity: f32,
pub textures: HashMap<String, TextureType>, pub textures: Vec<Texture>
} }
impl Material { impl Material {
fn new(name: String, ambient: glm::Vec3, diffuse: glm::Vec3, specular: glm::Vec3, shininess: f32, opacity: f32, textures: HashMap<String, TextureType>) -> Self { fn new(name: String, ambient: glm::Vec3, diffuse: glm::Vec3, specular: glm::Vec3, shininess: f32, opacity: f32, textures: Vec<Texture>) -> Self {
Self { Self {
name, name,
ambient_color: ambient, ambient_color: ambient,
@@ -53,7 +69,7 @@ impl Default for Material {
specular_color: glm::vec3(0.1, 0.1, 0.1), specular_color: glm::vec3(0.1, 0.1, 0.1),
specular_exponent: 32.0, specular_exponent: 32.0,
opacity: 1.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 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!( write!(
f, f,
"Ambient: {:?}\nDiffuse: {:?}\nSpecular: {:?}\nShininess: {}\nOpacity: {}", "Ambient: {:?}\nDiffuse: {:?}\nSpecular: {:?}\nShininess: {}\nOpacity: {}\nTextures: {:?}",
self.ambient_color, self.ambient_color,
self.diffuse_color, self.diffuse_color,
self.specular_color, self.specular_color,
self.specular_exponent, 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<Self, Box<dyn std::error::Error>> {
let id = utils::load_texture(path)?;
Ok(Texture {
id,
typ,
})
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct ObjMesh { pub struct ObjMesh {
pub name: String, pub name: String,
@@ -84,7 +119,7 @@ pub struct ObjMesh {
pub struct Object { pub struct Object {
pub name: String, pub name: String,
pub meshes: Vec<ObjMesh>, pub meshes: Vec<ObjMesh>,
pub aabb: AABB pub aabb: AABB,
} }
pub fn load_from_file(path: &PathBuf) -> Result<Object, Box<dyn std::error::Error>> { pub fn load_from_file(path: &PathBuf) -> Result<Object, Box<dyn std::error::Error>> {
+34 -8
View File
@@ -2,7 +2,7 @@ use std::{io::{BufReader, BufRead}, collections::HashMap, path::PathBuf};
use log::{error, warn, trace}; 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 const BUF_CAP: usize = 1024 * 128; // 128 Kilobytes
@@ -84,7 +84,7 @@ impl MtlToken {
} }
} }
fn parse_mtl(path: &PathBuf) -> Result<HashMap<String, Material>, Box<dyn std::error::Error>> { fn parse_mtl(path: &PathBuf, obj_textures: &mut HashMap<String, Texture>) -> Result<HashMap<String, Material>, Box<dyn std::error::Error>> {
let file = std::fs::File::open(path)?; let file = std::fs::File::open(path)?;
let reader = BufReader::with_capacity(BUF_CAP, file); let reader = BufReader::with_capacity(BUF_CAP, file);
let mut material_name = String::new(); let mut material_name = String::new();
@@ -95,6 +95,7 @@ fn parse_mtl(path: &PathBuf) -> Result<HashMap<String, Material>, Box<dyn std::e
let mut specular = glm::vec3(0.0, 0.0, 0.0); let mut specular = glm::vec3(0.0, 0.0, 0.0);
let mut shininess = 32.0; let mut shininess = 32.0;
let mut opacity = 1.0; let mut opacity = 1.0;
let mut mat_textures: Vec<Texture> = Vec::new();
for line in reader.lines() { for line in reader.lines() {
let line = line?; let line = line?;
@@ -109,8 +110,10 @@ fn parse_mtl(path: &PathBuf) -> Result<HashMap<String, Material>, Box<dyn std::e
match MtlToken::from_str(token) { match MtlToken::from_str(token) {
Some(MtlToken::NewMaterial) => { Some(MtlToken::NewMaterial) => {
if !material_name.is_empty() { 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); materials.insert(material_name, material);
mat_textures.clear();
} }
material_name = iter.next().unwrap().to_string(); material_name = iter.next().unwrap().to_string();
@@ -139,15 +142,36 @@ fn parse_mtl(path: &PathBuf) -> Result<HashMap<String, Material>, Box<dyn std::e
Some(MtlToken::Opacity) => { Some(MtlToken::Opacity) => {
opacity = iter.next().unwrap().parse::<f32>().unwrap(); opacity = iter.next().unwrap().parse::<f32>().unwrap();
} }
Some(MtlToken::DiffuseTexture) => { Some(MtlToken::DiffuseTexture)
// TODO: textures | 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) }, _ => { 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); materials.insert(material_name, material);
@@ -170,6 +194,7 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
let mut current_material: Option<Material> = None; let mut current_material: Option<Material> = None;
let mut min_aabb = glm::vec3(f32::MAX, f32::MAX, f32::MAX); 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 max_aabb = glm::vec3(f32::MIN, f32::MIN, f32::MIN);
let mut textures = HashMap::new();
for line in reader.lines() { for line in reader.lines() {
let line = line?; let line = line?;
@@ -264,7 +289,8 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
.map(|i| i.parse::<f32>().unwrap()); .map(|i| i.parse::<f32>().unwrap());
let u = iter.next().unwrap(); let u = iter.next().unwrap();
let v = 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) => { Some(ObjToken::Face) => {
let face = iter.collect::<Vec<_>>(); let face = iter.collect::<Vec<_>>();
@@ -372,7 +398,7 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
Some(ObjToken::MaterialLib) => { Some(ObjToken::MaterialLib) => {
for matlib in iter { for matlib in iter {
let material_path = obj_path.parent().unwrap().join(matlib); 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 { match new_materials {
Ok(m) => { Ok(m) => {
materials.extend(m); materials.extend(m);
+1 -1
View File
@@ -264,7 +264,7 @@ fn main() -> anyhow::Result<(), Box<dyn std::error::Error>> {
} else { } else {
gl::PolygonMode(gl::FRONT_AND_BACK, gl::FILL); 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); gl::PolygonMode(gl::FRONT_AND_BACK, gl::FILL);
+39 -49
View File
@@ -1,6 +1,7 @@
use glad_gl::gl; 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 { fn create_rotation_matrix(pitch: f32, yaw: f32, roll: f32, pivot: glm::Vec3) -> glm::Mat4 {
let pitch = pitch.to_radians(); let pitch = pitch.to_radians();
@@ -36,7 +37,6 @@ pub struct Mesh {
pub vertices: Vec<Vertex>, pub vertices: Vec<Vertex>,
pub indices: Vec<u32>, pub indices: Vec<u32>,
// pub textures: Vec<Texture>,
pub material: Material, pub material: Material,
vao: u32, vao: u32,
@@ -82,7 +82,6 @@ impl Mesh {
name: name.to_string(), name: name.to_string(),
vertices, vertices,
indices, indices,
// textures,
material: material.unwrap_or_default(), material: material.unwrap_or_default(),
vbo, vbo,
vao, vao,
@@ -94,16 +93,15 @@ impl Mesh {
} }
} }
pub fn draw(&self, shader: &Shader, scale: f32, pivot: glm::Vec3) { pub fn draw(&self, shader: &Shader, scale: f32, pivot: glm::Vec3, show_textures: bool) {
// let mut diffuse = 1;
// let mut specular = 1;
shader.use_shader(); shader.use_shader();
let model_mat = glm::ext::scale(&utils::mat_ident(), glm::vec3(scale, scale, scale)); 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 = 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)); 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); shader.set_mat4fv("model", &model_mat);
if glm::ext::is_invertible(&model_mat) {
let normal_mat = glm::transpose(&glm::inverse(&model_mat)); let normal_mat = glm::transpose(&glm::inverse(&model_mat));
let normal_mat = glm::mat3( let normal_mat = glm::mat3(
normal_mat[0][0], normal_mat[0][1], normal_mat[0][2], normal_mat[0][0], normal_mat[0][1], normal_mat[0][2],
@@ -111,6 +109,10 @@ impl Mesh {
normal_mat[2][0], normal_mat[2][1], normal_mat[2][2], normal_mat[2][0], normal_mat[2][1], normal_mat[2][2],
); );
shader.set_mat3fv("normalMatrix", &normal_mat); shader.set_mat3fv("normalMatrix", &normal_mat);
shader.set_bool("useNormalMatrix", true);
} else {
shader.set_bool("useNormalMatrix", false);
}
let mut polygon_mode = 0; let mut polygon_mode = 0;
unsafe { unsafe {
@@ -119,34 +121,44 @@ impl Mesh {
let is_wireframe = polygon_mode as u32 == gl::LINE; let is_wireframe = polygon_mode as u32 == gl::LINE;
if !is_wireframe { 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.ambient", self.material.ambient_color);
shader.set_3fv("material.diffuse", self.material.diffuse_color); shader.set_3fv("material.diffuse", self.material.diffuse_color);
shader.set_3fv("material.specular", self.material.specular_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 { } else {
shader.set_3fv("material.ambient", glm::vec3(0.0, 0.0, 0.0)); 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)); shader.set_3fv("material.diffuse", glm::vec3(0.0, 0.0, 0.0));
} }
// for i in 0..self.textures.len() { if show_textures {
// unsafe { shader.set_bool("useTextures", self.material.textures.len() > 0);
// gl::ActiveTexture(gl::TEXTURE0 + i as u32); for (i, tex) in self.material.textures.iter().enumerate() {
// match self.textures[i].typ { unsafe {
// russimp::material::TextureType::Diffuse => { gl::ActiveTexture(gl::TEXTURE0 + i as u32);
// diffuse += 1; match tex.typ {
// shader.set_int(format!("material.texture_diffuse{}", diffuse).as_str(), i as i32); TextureType::Ambient => {
// }, shader.set_int("material.texture_ambient", i as i32);
// russimp::material::TextureType::Specular => { },
// specular += 1; TextureType::Diffuse => {
// shader.set_int(format!("material.texture_specular{}", specular).as_str(), i as i32); shader.set_int("material.texture_diffuse", i as i32);
// }, },
// _ => {}, // don't do anything because unsupported texture types are logged TextureType::Specular => {
// // when the model is loaded 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 { unsafe {
// draw Mesh // draw Mesh
@@ -170,6 +182,7 @@ impl Mesh {
impl Drop for Mesh { impl Drop for Mesh {
fn drop(&mut self) { fn drop(&mut self) {
// TODO: should we impl a Drop on material to delete the textures from gpu??
unsafe { unsafe {
gl::BindVertexArray(0); gl::BindVertexArray(0);
gl::DeleteBuffers(1, &self.vbo); 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<Self, Box<dyn std::error::Error>> {
// 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,
// })
// }
// }
+2 -51
View File
@@ -12,55 +12,6 @@ pub struct Model {
pub mem_usage: usize, 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<Texture>
// ) -> (Vec<Texture>, Vec<Box<dyn std::error::Error>>) {
// 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 { impl Model {
pub fn new(obj: importer::Object, state: &mut ui::State) -> Model { pub fn new(obj: importer::Object, state: &mut ui::State) -> Model {
let mut meshes = Vec::new(); let mut meshes = Vec::new();
@@ -90,7 +41,7 @@ impl Model {
return 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_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_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; 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 { for mesh in &self.meshes {
mesh.draw(shader, self.scaling_factor, pivot); mesh.draw(shader, self.scaling_factor, pivot, show_textures);
} }
if draw_aabb { if draw_aabb {
+4
View File
@@ -31,6 +31,7 @@ pub struct State {
pub logger: logger::WritableLog, pub logger: logger::WritableLog,
pub settings: Settings, pub settings: Settings,
pub fps: f32, pub fps: f32,
pub show_textures: bool
} }
impl Default for State { impl Default for State {
@@ -55,6 +56,7 @@ impl Default for State {
logger: logger::WritableLog::default(), logger: logger::WritableLog::default(),
settings: Settings::default(), settings: Settings::default(),
fps: 0.0, 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.same_line();
ui.checkbox("FOV zoom", &mut state.fov_zoom); ui.checkbox("FOV zoom", &mut state.fov_zoom);
ui.same_line(); ui.same_line();
ui.checkbox("Show Textures", &mut state.show_textures);
ui.same_line();
ui.set_next_item_width(150.0); ui.set_next_item_width(150.0);
imgui::Drag::new("Camera Speed") imgui::Drag::new("Camera Speed")
.range(1.0, 10000.0) .range(1.0, 10000.0)
+9 -4
View File
@@ -22,11 +22,11 @@ impl SupportedFileExtensions {
} }
} }
pub fn load_texture(path: &str) -> Result<u32> { pub fn load_texture(path: PathBuf) -> Result<u32> {
let tex = image::io::Reader::open(path) let tex = image::io::Reader::open(path.clone())
.with_context(|| format!("Failed to open texture file: {}", path))? .with_context(|| format!("Failed to open texture file: {:?}", path))?
.decode() .decode()
.with_context(|| format!("Failed to decode texture: {}", path))?; .with_context(|| format!("Failed to decode texture: {:?}", path))?;
let mut texture_id: u32 = 0; let mut texture_id: u32 = 0;
let format = match tex.color().channel_count() { let format = match tex.color().channel_count() {
@@ -38,6 +38,9 @@ pub fn load_texture(path: &str) -> Result<u32> {
}; };
unsafe { 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::GenTextures(1, &mut texture_id);
gl::BindTexture(gl::TEXTURE_2D, texture_id); gl::BindTexture(gl::TEXTURE_2D, texture_id);
@@ -49,6 +52,8 @@ pub fn load_texture(path: &str) -> Result<u32> {
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::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::GenerateMipmap(gl::TEXTURE_2D);
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 4);
} }
Ok(texture_id) Ok(texture_id)