WIP: normal maps

This commit is contained in:
2023-11-04 21:40:01 +02:00
parent b403495da2
commit 43c9111a8c
12 changed files with 320 additions and 43 deletions
+1
View File
@@ -3,3 +3,4 @@
3rdparty/*/target 3rdparty/*/target
models/**/* models/**/*
3dobs.log 3dobs.log
capture-*
+4
View File
@@ -35,5 +35,9 @@
- [x] Shortcuts/keybinds window under the 'Help' menu item - [x] Shortcuts/keybinds window under the 'Help' menu item
- [x] Texture support (basic, but it's there) - [x] Texture support (basic, but it's there)
- [ ] Make model loading async and show a loading indicator, instead of blocking the main thread - [ ] Make model loading async and show a loading indicator, instead of blocking the main thread
- [ ] Multi-thread the texture loading and then join all threads before finishing the model loading func
- [ ] (BUG) Loading the Kairi model creates a weird red specular on it, and a weird blue specular on the nier model. I imagine other models are also affected
- [ ] Add support for .fbx (if it's an easy enough format, otherwise we'll look into something else)
- [ ] Draw a gizmo thingy for the light sources in the viewport
- [ ] Bring back the regular camera movement (can maybe be a switch between them) (for later) - [ ] Bring back the regular camera movement (can maybe be a switch between them) (for later)
+21 -9
View File
@@ -2,6 +2,7 @@
in vec3 fragNormals; in vec3 fragNormals;
in vec3 fragPos; in vec3 fragPos;
in vec2 texCoords; in vec2 texCoords;
in mat3 fragTBN;
out vec4 FragColor; out vec4 FragColor;
@@ -10,6 +11,7 @@ struct Material {
sampler2D texture_specular; sampler2D texture_specular;
sampler2D texture_ambient; sampler2D texture_ambient;
sampler2D texture_emission; sampler2D texture_emission;
sampler2D texture_normal;
vec3 ambient; vec3 ambient;
vec3 diffuse; vec3 diffuse;
@@ -63,6 +65,7 @@ uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform SpotLight spotLight; uniform SpotLight spotLight;
uniform bool useTextures; uniform bool useTextures;
uniform bool hasEmissionTexture; uniform bool hasEmissionTexture;
uniform bool hasNormalTexture;
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);
@@ -83,9 +86,9 @@ vec3 CalculateDirLight(DirLight light, vec3 normal, vec3 viewDir) {
vec3 specular = vec3(0.0, 0.0, 0.0); vec3 specular = vec3(0.0, 0.0, 0.0);
if (useTextures) { if (useTextures) {
ambient = light.ambient * vec3(texture(material.texture_ambient, texCoords)) * material.ambient; ambient = light.ambient * vec3(texture(material.texture_ambient, texCoords));
diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse, texCoords)) * material.diffuse; diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse, texCoords));
specular = light.specular * spec * vec3(texture(material.texture_specular, texCoords)) * material.specular; specular = light.specular * spec * vec3(texture(material.texture_specular, texCoords));
} else { } else {
ambient = light.ambient * material.ambient; ambient = light.ambient * material.ambient;
diffuse = light.diffuse * (diff * material.diffuse); diffuse = light.diffuse * (diff * material.diffuse);
@@ -118,9 +121,9 @@ vec3 CalculatePointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewD
vec3 specular = vec3(0.0, 0.0, 0.0); vec3 specular = vec3(0.0, 0.0, 0.0);
if (useTextures) { if (useTextures) {
ambient = light.ambient * vec3(texture(material.texture_ambient, texCoords)) * material.ambient; ambient = light.ambient * vec3(texture(material.texture_ambient, texCoords));
diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse, texCoords)) * material.diffuse; diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse, texCoords));
specular = light.specular * spec * vec3(texture(material.texture_specular, texCoords)) * material.specular; specular = light.specular * spec * vec3(texture(material.texture_specular, texCoords));
} else { } else {
ambient = light.ambient * material.ambient; ambient = light.ambient * material.ambient;
diffuse = light.diffuse * (diff * material.diffuse); diffuse = light.diffuse * (diff * material.diffuse);
@@ -162,9 +165,9 @@ vec3 CalculateSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir
vec3 specular = vec3(0.0, 0.0, 0.0); vec3 specular = vec3(0.0, 0.0, 0.0);
if (useTextures) { if (useTextures) {
ambient = light.ambient * vec3(texture(material.texture_ambient, texCoords)) * material.ambient; ambient = light.ambient * vec3(texture(material.texture_ambient, texCoords));
diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse, texCoords)) * material.diffuse; diffuse = light.diffuse * diff * vec3(texture(material.texture_diffuse, texCoords));
specular = light.specular * spec * vec3(texture(material.texture_specular, texCoords)) * material.specular; specular = light.specular * spec * vec3(texture(material.texture_specular, texCoords));
} else { } else {
ambient = light.ambient * material.ambient; ambient = light.ambient * material.ambient;
diffuse = light.diffuse * (diff * material.diffuse); diffuse = light.diffuse * (diff * material.diffuse);
@@ -190,6 +193,14 @@ void main()
} }
vec3 norm = normalize(fragNormals); vec3 norm = normalize(fragNormals);
// use normal map if available
if (useTextures && hasNormalTexture) {
vec3 normal = texture(material.texture_normal, texCoords).rgb;
normal = normal * 2.0 - 1.0;
norm = normalize(fragTBN * normal);
}
vec3 viewDir = normalize(viewPos - fragPos); vec3 viewDir = normalize(viewPos - fragPos);
// direction light // direction light
@@ -202,6 +213,7 @@ void main()
result += CalculateSpotLight(spotLight, norm, fragPos, viewDir); result += CalculateSpotLight(spotLight, norm, fragPos, viewDir);
// emission
if (useTextures && hasEmissionTexture) { if (useTextures && hasEmissionTexture) {
result += texture(material.texture_emission, texCoords).rgb; result += texture(material.texture_emission, texCoords).rgb;
} }
+10
View File
@@ -2,9 +2,12 @@
layout (location = 0) in vec3 aPos; layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal; layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords; layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in vec3 aTangent;
layout (location = 4) in vec3 aBitangent;
out vec3 fragNormals; out vec3 fragNormals;
out vec3 fragPos; out vec3 fragPos;
out vec2 texCoords; out vec2 texCoords;
out mat3 fragTBN;
uniform mat4 model; uniform mat4 model;
uniform mat4 view; uniform mat4 view;
@@ -19,7 +22,14 @@ void main()
fragNormals = normalMatrix * aNormal; fragNormals = normalMatrix * aNormal;
else else
fragNormals = mat3(transpose(inverse(model))) * aNormal; fragNormals = mat3(transpose(inverse(model))) * aNormal;
vec3 T = normalize(vec3(model * vec4(aTangent, 0.0)));
vec3 B = normalize(vec3(model * vec4(aBitangent, 0.0)));
vec3 N = normalize(vec3(model * vec4(aNormal, 0.0)));
mat3 TBN = mat3(T, B, N);
fragPos = vec3(model * vec4(aPos, 1.0)); fragPos = vec3(model * vec4(aPos, 1.0));
texCoords = aTexCoords; texCoords = aTexCoords;
fragTBN = TBN;
} }
+56 -8
View File
@@ -19,14 +19,62 @@ impl AABB {
let mut ebo = 0; let mut ebo = 0;
let vertices = vec![ let vertices = vec![
Vertex { position: glm::vec3(min.x, min.y, min.z), tex_coords: glm::vec2(0.0, 0.0), normal: glm::vec3(0.0, 0.0, 0.0) }, Vertex {
Vertex { position: glm::vec3(max.x, min.y, min.z), tex_coords: glm::vec2(1.0, 0.0), normal: glm::vec3(0.0, 0.0, 0.0) }, position: glm::vec3(min.x, min.y, min.z),
Vertex { position: glm::vec3(max.x, max.y, min.z), tex_coords: glm::vec2(1.0, 1.0), normal: glm::vec3(0.0, 0.0, 0.0) }, tex_coords: glm::vec2(0.0, 0.0),
Vertex { position: glm::vec3(min.x, max.y, min.z), tex_coords: glm::vec2(0.0, 1.0), normal: glm::vec3(0.0, 0.0, 0.0) }, normal: glm::vec3(0.0, 0.0, 0.0),
Vertex { position: glm::vec3(min.x, min.y, max.z), tex_coords: glm::vec2(0.0, 0.0), normal: glm::vec3(0.0, 0.0, 0.0) }, tangent: glm::vec3(0.0, 0.0, 0.0),
Vertex { position: glm::vec3(max.x, min.y, max.z), tex_coords: glm::vec2(1.0, 0.0), normal: glm::vec3(0.0, 0.0, 0.0) }, bitangent: glm::vec3(0.0, 0.0, 0.0),
Vertex { position: glm::vec3(max.x, max.y, max.z), tex_coords: glm::vec2(1.0, 1.0), normal: glm::vec3(0.0, 0.0, 0.0) }, },
Vertex { position: glm::vec3(min.x, max.y, max.z), tex_coords: glm::vec2(0.0, 1.0), normal: glm::vec3(0.0, 0.0, 0.0) }, Vertex {
position: glm::vec3(max.x, min.y, min.z),
tex_coords: glm::vec2(1.0, 0.0),
normal: glm::vec3(0.0, 0.0, 0.0),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0),
},
Vertex {
position: glm::vec3(max.x, max.y, min.z),
tex_coords: glm::vec2(1.0, 1.0),
normal: glm::vec3(0.0, 0.0, 0.0),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0),
},
Vertex {
position: glm::vec3(min.x, max.y, min.z),
tex_coords: glm::vec2(0.0, 1.0),
normal: glm::vec3(0.0, 0.0, 0.0),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0),
},
Vertex {
position: glm::vec3(min.x, min.y, max.z),
tex_coords: glm::vec2(0.0, 0.0),
normal: glm::vec3(0.0, 0.0, 0.0),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0),
},
Vertex {
position: glm::vec3(max.x, min.y, max.z),
tex_coords: glm::vec2(1.0, 0.0),
normal: glm::vec3(0.0, 0.0, 0.0),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0),
},
Vertex {
position: glm::vec3(max.x, max.y, max.z),
tex_coords: glm::vec2(1.0, 1.0),
normal: glm::vec3(0.0, 0.0, 0.0),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0),
},
Vertex {
position: glm::vec3(min.x, max.y, max.z),
tex_coords: glm::vec2(0.0, 1.0),
normal: glm::vec3(0.0, 0.0, 0.0),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0),
},
]; ];
let indices = vec![ let indices = vec![
+4 -1
View File
@@ -25,7 +25,10 @@ impl TextureType {
"map_Kd" => Some(TextureType::Diffuse), "map_Kd" => Some(TextureType::Diffuse),
"map_Ks" => Some(TextureType::Specular), "map_Ks" => Some(TextureType::Specular),
"map_Ns" => Some(TextureType::SpecularHighlight), "map_Ns" => Some(TextureType::SpecularHighlight),
"map_bump" => Some(TextureType::Bump), "map_Bump" => Some(TextureType::Bump),
"bump" => Some(TextureType::Bump),
"norm" => Some(TextureType::Bump),
"map_Kn" => Some(TextureType::Bump),
"map_d" => Some(TextureType::Displacement), "map_d" => Some(TextureType::Displacement),
"decal" => Some(TextureType::Decal), "decal" => Some(TextureType::Decal),
"refl" => Some(TextureType::Reflection), "refl" => Some(TextureType::Reflection),
+174 -8
View File
@@ -1,6 +1,6 @@
use std::{io::{BufReader, BufRead}, collections::HashMap, path::PathBuf}; use std::{io::{BufReader, BufRead}, collections::HashMap, path::PathBuf};
use log::{error, warn, trace}; use log::{error, warn, trace, info};
use crate::{mesh::Vertex, aabb::AABB, importer::{ObjMesh, Object, Material, Texture, TextureType}}; use crate::{mesh::Vertex, aabb::AABB, importer::{ObjMesh, Object, Material, Texture, TextureType}};
@@ -77,7 +77,11 @@ impl MtlToken {
"map_Ks" => Some(MtlToken::SpecularTexture), "map_Ks" => Some(MtlToken::SpecularTexture),
"map_Ns" => Some(MtlToken::SpecularHighlightTexture), "map_Ns" => Some(MtlToken::SpecularHighlightTexture),
"map_Ke" => Some(MtlToken::EmissiveTexture), "map_Ke" => Some(MtlToken::EmissiveTexture),
"map_bump" => Some(MtlToken::BumpTexture), "map_Bump" => Some(MtlToken::BumpTexture),
"bump" => Some(MtlToken::BumpTexture),
// "map_Kn" => Some(MtlToken::BumpTexture), // non-standard, we don't
// yet know if it specifies a bump parameter so we let it log a warning
"norm" => Some(MtlToken::BumpTexture),
"map_d" => Some(MtlToken::DisplacementTexture), "map_d" => Some(MtlToken::DisplacementTexture),
"decal" => Some(MtlToken::DecalTexture), "decal" => Some(MtlToken::DecalTexture),
"refl" => Some(MtlToken::ReflectionTexture), "refl" => Some(MtlToken::ReflectionTexture),
@@ -174,7 +178,49 @@ fn parse_mtl(path: &PathBuf, obj_textures: &mut HashMap<String, Texture>) -> Res
tex tex
}; };
mat_textures.push(mat); mat_textures.push(tex);
}
Some(MtlToken::BumpTexture) => {
// norm doesn't specify a bump parameter
// map_bump does
let mut bm = 1.0;
let mut name = String::new();
let next = iter.next().unwrap();
if next == "-bm" {
bm = iter.next().unwrap().parse::<f32>().unwrap();
name = iter.next().unwrap().to_string();
} else {
name = next.to_string();
if let Some(possible_bump) = iter.next() {
if possible_bump == "-bm" {
bm = iter.next().unwrap().parse::<f32>().unwrap();
}
}
}
let tex = if obj_textures.contains_key(&name) {
let mut tex = obj_textures.get(&name).unwrap().clone();
tex.typ = TextureType::Bump;
tex
} else {
let path = path.parent().unwrap().join(&name);
let tex = match Texture::new(path, TextureType::Bump) {
Ok(v) => v,
Err(e) => {
error!("Failed to load texture: {}", e);
continue;
}
};
obj_textures.insert(name, tex.clone());
tex
};
// TODO: use bm somewhere
mat_textures.push(tex);
} }
_ => { warn!("Unhandled material token: {}", token) }, _ => { warn!("Unhandled material token: {}", token) },
} }
@@ -335,7 +381,9 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
vertices.push(Vertex{ vertices.push(Vertex{
position: *temp_vertices.get(vert as usize).unwrap(), position: *temp_vertices.get(vert as usize).unwrap(),
normal: *normals.get(normal as usize).unwrap(), normal: *normals.get(normal as usize).unwrap(),
tex_coords: glm::vec2(0.0, 0.0) tex_coords: glm::vec2(0.0, 0.0),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0)
}); });
} else if vert.matches("/").count() == 2 { } else if vert.matches("/").count() == 2 {
let mut it = vert.split("/"); let mut it = vert.split("/");
@@ -360,7 +408,9 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
vertices.push(Vertex{ vertices.push(Vertex{
position: *temp_vertices.get(vertex as usize).unwrap(), position: *temp_vertices.get(vertex as usize).unwrap(),
normal: *normals.get(normal as usize).unwrap(), normal: *normals.get(normal as usize).unwrap(),
tex_coords: *tex_coords.get(t_coords as usize).unwrap() tex_coords: *tex_coords.get(t_coords as usize).unwrap(),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0)
}); });
} else if vert.matches("/").count() == 1 { } else if vert.matches("/").count() == 1 {
let mut it = vert.split("/"); let mut it = vert.split("/");
@@ -379,7 +429,9 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
vertices.push(Vertex{ vertices.push(Vertex{
position: *temp_vertices.get(vertex as usize).unwrap(), position: *temp_vertices.get(vertex as usize).unwrap(),
normal: calculated_normal, normal: calculated_normal,
tex_coords: *tex_coords.get(t_coords as usize).unwrap() tex_coords: *tex_coords.get(t_coords as usize).unwrap(),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0)
}); });
} else { } else {
let mut vert = vert.parse::<i32>().unwrap(); let mut vert = vert.parse::<i32>().unwrap();
@@ -392,10 +444,12 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
position: *temp_vertices.get(vert as usize).unwrap(), position: *temp_vertices.get(vert as usize).unwrap(),
normal: calculated_normal, normal: calculated_normal,
tex_coords: glm::vec2(0.0, 0.0), tex_coords: glm::vec2(0.0, 0.0),
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0)
}); });
} }
// Triangulate faces. 2 triangles per face // Triangulate faces
if i < face.len() - 2 { if i < face.len() - 2 {
indices.push(indices_counter); indices.push(indices_counter);
indices.push(indices_counter + i as u32 + 1); indices.push(indices_counter + i as u32 + 1);
@@ -403,6 +457,84 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
} }
} }
// println!("indices counter: {}", indices_counter);
// println!("indices: {:?}", indices);
for i in 0..face.len() - 2 {
// let vert1 = &vertices[indices[indices_counter as usize] as usize];
// let vert2 = &vertices[indices[indices_counter as usize + 1 + i] as usize];
// let vert3 = &vertices[indices[indices_counter as usize + 2 + i] as usize];
// let edge1 = vert2.position - vert1.position;
// let edge2 = vert3.position - vert1.position;
// let delta_uv1 = vert2.tex_coords - vert1.tex_coords;
// let delta_uv2 = vert3.tex_coords - vert1.tex_coords;
// let f = 1.0 / (delta_uv1.x * delta_uv2.y - delta_uv2.x * delta_uv1.y);
// let tangent = glm::vec3(
// f * (delta_uv2.y * edge1.x - delta_uv1.y * edge2.x),
// f * (delta_uv2.y * edge1.y - delta_uv1.y * edge2.y),
// f * (delta_uv2.y * edge1.z - delta_uv1.y * edge2.z),
// );
// let bitangent = glm::vec3(
// f * (-delta_uv2.x * edge1.x + delta_uv1.x * edge2.x),
// f * (-delta_uv2.x * edge1.y + delta_uv1.x * edge2.y),
// f * (-delta_uv2.x * edge1.z + delta_uv1.x * edge2.z),
// );
// vertices[indices[indices_counter as usize] as usize].tangent = vertices[indices[indices_counter as usize] as usize].tangent + tangent;
// vertices[indices[indices_counter as usize + 1 + i] as usize].tangent = vertices[indices[indices_counter as usize + 1 + i] as usize].tangent + tangent;
// vertices[indices[indices_counter as usize + 2 + i] as usize].tangent = vertices[indices[indices_counter as usize + 2 + i] as usize].tangent + tangent;
// vertices[indices[indices_counter as usize] as usize].bitangent = bitangent;
// vertices[indices[indices_counter as usize + 1 + i] as usize].bitangent = bitangent;
// vertices[indices[indices_counter as usize + 2 + i] as usize].bitangent = bitangent;
// println!("tangent: {:?}", tangent);
// println!("bitangent: {:?}", bitangent);
let index1 = indices_counter as usize;
let index2 = indices_counter as usize + i + 1;
let index3 = indices_counter as usize + i + 2;
let vert1 = &vertices[index1];
let vert2 = &vertices[index2];
let vert3 = &vertices[index3];
// println!("vert1: {:?}", vert1);
// println!("vert2: {:?}", vert2);
// println!("vert3: {:?}", vert3);
let edge1 = vert2.position - vert1.position;
let edge2 = vert3.position - vert1.position;
let delta_uv1 = vert2.tex_coords - vert1.tex_coords;
let delta_uv2 = vert3.tex_coords - vert1.tex_coords;
let f = 1.0 / (delta_uv1.x * delta_uv2.y - delta_uv2.x * delta_uv1.y);
let temp_tangent = glm::vec3(
f * (delta_uv2.y * edge1.x - delta_uv1.y * edge2.x),
f * (delta_uv2.y * edge1.y - delta_uv1.y * edge2.y),
f * (delta_uv2.y * edge1.z - delta_uv1.y * edge2.z),
);
let tangent = glm::normalize(temp_tangent - vert1.normal * glm::dot(vert1.normal, temp_tangent));
let bitangent = glm::cross(vert1.normal, tangent);
vertices[index1].tangent = vertices[index1].tangent + tangent;
vertices[index2].tangent = vertices[index2].tangent + tangent;
vertices[index3].tangent = vertices[index3].tangent + tangent;
vertices[index1].bitangent = vertices[index1].bitangent + bitangent;
vertices[index2].bitangent = vertices[index2].bitangent + bitangent;
vertices[index3].bitangent = vertices[index3].bitangent + bitangent;
// println!("tangent: {:?}", tangent);
// println!("bitangent: {:?}", bitangent);
}
indices_counter += face.len() as u32; indices_counter += face.len() as u32;
} }
Some(ObjToken::MaterialLib) => { Some(ObjToken::MaterialLib) => {
@@ -457,7 +589,7 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
} }
} }
let elapsed = now.elapsed(); let elapsed = now.elapsed();
trace!("Loaded in {}ms", elapsed.as_millis()); info!("Loaded in {}ms", elapsed.as_millis());
let mesh_name = { let mesh_name = {
if current_mesh_name.is_empty() && !object_name.is_empty() { if current_mesh_name.is_empty() && !object_name.is_empty() {
@@ -469,6 +601,40 @@ pub fn load_obj(obj_path: &PathBuf, file: std::fs::File) -> Result<Object, Box<d
} }
}; };
// for i in (0..indices.len()).step_by(3) {
// let index1 = indices[i] as usize;
// let index2 = indices[i + 1] as usize;
// let index3 = indices[i + 2] as usize;
// let vert1 = &vertices[index1];
// let vert2 = &vertices[index2];
// let vert3 = &vertices[index3];
// let edge1 = vert2.position - vert1.position;
// let edge2 = vert3.position - vert1.position;
// let delta_uv1 = vert2.tex_coords - vert1.tex_coords;
// let delta_uv2 = vert3.tex_coords - vert1.tex_coords;
// let f = 1.0 / (delta_uv1.x * delta_uv2.y - delta_uv2.x * delta_uv1.y);
// let temp_tangent = glm::vec3(
// f * (delta_uv2.y * edge1.x - delta_uv1.y * edge2.x),
// f * (delta_uv2.y * edge1.y - delta_uv1.y * edge2.y),
// f * (delta_uv2.y * edge1.z - delta_uv1.y * edge2.z),
// );
// let tangent = glm::normalize(temp_tangent - vert1.normal * glm::dot(vert1.normal, temp_tangent));
// let bitangent = glm::cross(vert1.normal, tangent);
// vertices[index1].tangent = vertices[index1].tangent + tangent;
// vertices[index2].tangent = vertices[index2].tangent + tangent;
// vertices[index3].tangent = vertices[index3].tangent + tangent;
// vertices[index1].bitangent = vertices[index1].bitangent + bitangent;
// vertices[index2].bitangent = vertices[index2].bitangent + bitangent;
// vertices[index3].bitangent = vertices[index3].bitangent + bitangent;
// }
meshes.push(ObjMesh{ meshes.push(ObjMesh{
name: mesh_name, name: mesh_name,
vertices: vertices.clone(), vertices: vertices.clone(),
+4
View File
@@ -85,6 +85,8 @@ fn parse_ascii_stl(file: std::fs::File) -> Result<Object, Box<dyn std::error::Er
position: glm::vec3(vert.x, vert.y, vert.z), position: glm::vec3(vert.x, vert.y, vert.z),
normal: glm::vec3(triangle.normal.x, triangle.normal.y, triangle.normal.z), normal: glm::vec3(triangle.normal.x, triangle.normal.y, triangle.normal.z),
tex_coords, tex_coords,
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0),
}); });
min_aabb = glm::min(min_aabb, vert); min_aabb = glm::min(min_aabb, vert);
@@ -183,6 +185,8 @@ fn parse_binary_stl(mut file: std::fs::File) -> Result<Object, Box<dyn std::erro
position: glm::vec3(vert.x, vert.y, vert.z), position: glm::vec3(vert.x, vert.y, vert.z),
normal: glm::vec3(triangle.normal.x, triangle.normal.y, triangle.normal.z), normal: glm::vec3(triangle.normal.x, triangle.normal.y, triangle.normal.z),
tex_coords, tex_coords,
tangent: glm::vec3(0.0, 0.0, 0.0),
bitangent: glm::vec3(0.0, 0.0, 0.0),
}); });
min_aabb = glm::min(min_aabb, vert); min_aabb = glm::min(min_aabb, vert);
+2 -2
View File
@@ -147,7 +147,7 @@ fn main() -> anyhow::Result<(), Box<dyn std::error::Error>> {
mesh_shader.set_3fv("dirLight.direction", glm::vec3(-0.2, -1.0, -0.3)); mesh_shader.set_3fv("dirLight.direction", glm::vec3(-0.2, -1.0, -0.3));
mesh_shader.set_3fv("dirLight.ambient", glm::vec3(0.1, 0.1, 0.1)); mesh_shader.set_3fv("dirLight.ambient", glm::vec3(0.1, 0.1, 0.1));
mesh_shader.set_3fv("dirLight.diffuse", glm::vec3(1.0, 1.0, 1.0)); mesh_shader.set_3fv("dirLight.diffuse", glm::vec3(0.5, 0.5, 0.5));
mesh_shader.set_3fv("dirLight.specular", glm::vec3(1.0, 1.0, 1.0)); mesh_shader.set_3fv("dirLight.specular", glm::vec3(1.0, 1.0, 1.0));
let scene_fb = create_scene_framebuffer(); let scene_fb = create_scene_framebuffer();
@@ -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, state.show_textures);} if Some(obj.id) == state.active_model {obj.draw(&mesh_shader, state.draw_aabb, state.show_textures, state.show_normal, state.show_emission);}
} }
gl::PolygonMode(gl::FRONT_AND_BACK, gl::FILL); gl::PolygonMode(gl::FRONT_AND_BACK, gl::FILL);
+31 -10
View File
@@ -1,5 +1,4 @@
use glad_gl::gl; use glad_gl::gl;
use log::warn;
use crate::{shader::Shader, utils, importer::{Material, TextureType}}; use crate::{shader::Shader, utils, importer::{Material, TextureType}};
@@ -75,6 +74,14 @@ impl Mesh {
gl::EnableVertexAttribArray(2); gl::EnableVertexAttribArray(2);
gl::VertexAttribPointer(2, 2, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, (6 * std::mem::size_of::<f32>()) as *const std::ffi::c_void); gl::VertexAttribPointer(2, 2, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, (6 * std::mem::size_of::<f32>()) as *const std::ffi::c_void);
// vertex tangent
gl::EnableVertexAttribArray(3);
gl::VertexAttribPointer(3, 3, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, (8 * std::mem::size_of::<f32>()) as *const std::ffi::c_void);
// vertex bitangent
gl::EnableVertexAttribArray(4);
gl::VertexAttribPointer(4, 3, gl::FLOAT, gl::FALSE, std::mem::size_of::<Vertex>() as i32, (11 * std::mem::size_of::<f32>()) as *const std::ffi::c_void);
gl::BindVertexArray(0); gl::BindVertexArray(0);
} }
@@ -93,7 +100,7 @@ impl Mesh {
} }
} }
pub fn draw(&self, shader: &Shader, scale: f32, pivot: glm::Vec3, show_textures: bool) { pub fn draw(&self, shader: &Shader, scale: f32, pivot: glm::Vec3, show_textures: bool, use_normal: bool, use_emissive: bool) {
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));
@@ -135,11 +142,13 @@ impl Mesh {
if show_textures { if show_textures {
shader.set_bool("useTextures", self.material.textures.len() > 0); shader.set_bool("useTextures", self.material.textures.len() > 0);
for (i, tex) in self.material.textures.iter().enumerate() { shader.set_bool("hasNormalTexture", false);
shader.set_bool("hasEmissionTexture", false); shader.set_bool("hasEmissionTexture", false);
for i in 0..self.material.textures.len() {
unsafe { unsafe {
gl::ActiveTexture(gl::TEXTURE0 + i as u32); gl::ActiveTexture(gl::TEXTURE0 + i as u32);
match tex.typ { gl::BindTexture(gl::TEXTURE_2D, self.material.textures[i].id);
match self.material.textures[i].typ {
TextureType::Ambient => { TextureType::Ambient => {
shader.set_int("material.texture_ambient", i as i32); shader.set_int("material.texture_ambient", i as i32);
}, },
@@ -150,13 +159,20 @@ impl Mesh {
shader.set_int("material.texture_specular", i as i32); shader.set_int("material.texture_specular", i as i32);
}, },
TextureType::Emissive => { TextureType::Emissive => {
shader.set_int("material.texture_emission", i as i32); if use_emissive {
shader.set_bool("hasEmissionTexture", true); shader.set_bool("hasEmissionTexture", true);
}
shader.set_int("material.texture_emission", i as i32);
}, },
_ => {}, TextureType::Bump => {
if use_normal {
shader.set_bool("hasNormalTexture", true);
}
shader.set_int("material.texture_normal", i as i32);
},
_ => { continue; },
} }
gl::BindTexture(gl::TEXTURE_2D, tex.id);
} }
} }
} else { } else {
@@ -185,12 +201,13 @@ 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::ActiveTexture(gl::TEXTURE0);
gl::BindVertexArray(0); gl::BindVertexArray(0);
gl::DeleteBuffers(1, &self.vbo); gl::DeleteBuffers(1, &self.vbo);
gl::DeleteBuffers(1, &self.ebo); gl::DeleteBuffers(1, &self.ebo);
gl::DeleteVertexArrays(1, &self.vao); gl::DeleteVertexArrays(1, &self.vao);
gl::DeleteTextures(self.material.textures.len() as i32, self.material.textures.iter().map(|t| t.id).collect::<Vec<u32>>().as_ptr());
} }
} }
} }
@@ -201,14 +218,18 @@ pub struct Vertex {
pub position: glm::Vec3, pub position: glm::Vec3,
pub normal: glm::Vec3, pub normal: glm::Vec3,
pub tex_coords: glm::Vec2, pub tex_coords: glm::Vec2,
pub tangent: glm::Vec3,
pub bitangent: glm::Vec3,
} }
impl Vertex { impl Vertex {
pub fn new(position: glm::Vec3, normal: glm::Vec3, tex_coords: glm::Vec2) -> Self { pub fn new(position: glm::Vec3, normal: glm::Vec3, tex_coords: glm::Vec2, tangent: glm::Vec3, bitangent: glm::Vec3) -> Self {
Vertex { Vertex {
position, position,
normal, normal,
tex_coords tex_coords,
tangent,
bitangent,
} }
} }
} }
+2 -2
View File
@@ -41,7 +41,7 @@ impl Model {
return model; return model;
} }
pub fn draw(&self, shader: &Shader, draw_aabb: bool, show_textures: bool) { pub fn draw(&self, shader: &Shader, draw_aabb: bool, show_textures: bool, use_normal: bool, use_emissive: 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;
@@ -53,7 +53,7 @@ impl Model {
for mesh in &self.meshes { for mesh in &self.meshes {
mesh.draw(shader, self.scaling_factor, pivot, show_textures); mesh.draw(shader, self.scaling_factor, pivot, show_textures, use_normal, use_emissive);
} }
if draw_aabb { if draw_aabb {
+10 -2
View File
@@ -31,7 +31,9 @@ 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 pub show_textures: bool,
pub show_normal: bool,
pub show_emission: bool,
} }
impl Default for State { impl Default for State {
@@ -56,7 +58,9 @@ 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 show_textures: true,
show_normal: true,
show_emission: true,
} }
} }
} }
@@ -491,6 +495,10 @@ fn draw_viewport(ui: &imgui::Ui, state: &mut State, texture: u32) {
ui.same_line(); ui.same_line();
ui.checkbox("Show Textures", &mut state.show_textures); ui.checkbox("Show Textures", &mut state.show_textures);
ui.same_line(); ui.same_line();
ui.checkbox("Use Normal", &mut state.show_normal);
ui.same_line();
ui.checkbox("Use Emissive", &mut state.show_emission);
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)