From 38ea41b550074675943d8ccd59997c3f85a40f5d Mon Sep 17 00:00:00 2001 From: Asuro Date: Mon, 26 Oct 2020 18:15:39 +0100 Subject: [PATCH] Simple normal map implementation --- models/plane.glb | Bin 24523452 -> 24523636 bytes shaders/triangle.frag | 5 +++-- shaders/triangle.vert | 20 +++++++++++++++++--- src/main.rs | 10 +++++----- src/mesh.rs | 40 ++++++++++++++++++++++++++++------------ src/vulkan.rs | 5 +++-- 6 files changed, 56 insertions(+), 24 deletions(-) diff --git a/models/plane.glb b/models/plane.glb index db26e9cc986a7ba212ccb51e529efbec1c2a0fd4..ac6106602918397ecb326000d0366468ee333c63 100644 GIT binary patch delta 1852 zcmdn<^al5rXE(Tc({n=Hm>3usN{q`GFKpy}&Zz3>=kDqkqGV;HqZHyA;q31p}nU^VW@){=d$y1rc8OawGg$Utwi$zrxDVeub5@{R%5r`xRF1_A9JB?N?ZN+pnA_FQ2P~D;r1)6BJEdLMcc2iinU*16>q=7D$#z0RkHmGt5o|HR_XRDtTOFaSY_L< zu*$VxVU=&c!m7}Ig;lZr3ae846;|c;E37K*S6Efsudu4MUtv{mzrw1~euY)D{R*pA z`xRF0_A9J9?N?ZJ+pnA_FQTr8EPP1~=qnzdhH zHE+MdYSDg$)w2Bxt5y3IR_pdFtTydeSZ&*{u-dg>VYP3+!s^g|h1IeB3aeB56;|i= zE37WA^aQ2Q0u;Pxx5A?;UKL))*ghP7W|4R61~8qt1*HM0E*YgGFc*68*ttTF9Z zSYz9-u*S7tVU2IU!kW;2g*CDL3TsmP71reTE37H)S6EZqudt@IUtvvezrvc)euXu& z{R(SV`xVyg_A9J8?N?ZH+pnA^aQTr9v;`S@7CGA&OOWUuo zmbG7DEpNZVTG4)mwX*#RYgPLd*6Q{vtTpXdSZmv_u-3I-VXbe!!rIV&g|)H$3TspQ z71rkVE37T;S6ExyudueYUtw);zrxzleucHO{R(SW`xVyi_A9JC?N?ZP+pn(urutkc@BuugBk!aAe<3hT`FE3C8HudvQ; zzrs4F{R->c_A9LO+OM$AZ@(cfstjpT3ur6=E z!n&gU3hT=DE3B*9uduFezrwnv{R->a_A9LG+OM##Z@(=%wtlQeJux@X^!n&jV3hU1HE3CWPudwcJzrwnw{R->e_A9LW+OM$gZ@(TZrtjF4~upV!}!g`|p3hT-CE3Bv5udtqOzruQ^ z{R->Z_A9LC+OM#lZ@(%xvtk>GFuwHM!!g{0q z3hT}GE3CKLudv>3zruQ_{R->d_A9LS+OM$QZ@(llttk2r7us(0U!uq293hT@EE3B{Dudu#uzry;a{R->b_A9LK+OM#_Z@(}-xtl!$Nuzqj9!uq5A3hU4IE3CiTudx1Zzry;b{R->f z_A9La+OM$w@4mvy*nfqU5kxS72xbt$0wTZ?Y#2t){j2oVq=3L?ZnggA(h01=WPLJCAkg9sTAAqyhpK!iMqPyi8%AVLX5 zD1!(U5TObp)Ifwfh|mBLnjk_8L}-Hu9T1@lBJ@CnK8P>?5r!bb2t*iz2on%t3L?xv zggJt zM0kS;9}wXSBK$yvKZpnb5rH5g2t)*fh!7AF3L?TlL^z0u01=TOA__!AgNPUq5ep*X zKtw!DU9ROpE;2Hn` delta 1751 zcmezJ><0Iqr#HBH({n=Hm>3us_865hMr`DL&M4^`;q31p_puqY_puqa_puqZ_puqb_pzC@_pzC__pzC^_pzC`_pw>D z_pw>F_pw>E_pw>G_p#Zu_p#Zw_p#Zv_p#Zx_pv#&_pv#)_pv#(_pv#*_p!OO_p!OQ z_p!OP_p!OR_py1j_py1l_py1k_py1m_p$l3_p$l5_p$l4_p$l6_pt@E_pt@G_pt@F z_pt@H_pybv_pybx_pybw_pyby_pwE^_pwE`_pwE__pwE{_p!ya_p!yc_p!yb_p!yd z_pv3k_pv3m_pv3l_pv3n_pzn4_pzn6_pzn5_pzn7_pxQP_pxQR_pxQQ_pxQS_p#-) z_p#-+_p#-*_p#--_pueU_pueW_pueV_pueX_pz0<_pz0>_pz0=_pz0?_pw#9_pw#B z_pw#A_pw#C_p#Nq_p#Ns_p#Nr_p#Nt_pvp!_pvp$_pvp#_pvp%_p!CK_p!CM_p!CL z_p!CN_px=f_px=h_px=g_px=i_p$Y~_p$Z1_p$Z0_p$Z2_pwcA?_-(eQfL6``FgE_pxng?_=B8-p977y^n2kdmr1D_CB_)?R{+9+WXkHxA(E_Xzyd& z+1|&ttG$nHcY7b(p7uVrz3qK$``Y{1_P6)39cb@kJJ{aGcBs9N?QnY^+mZG@wxjKR zY{%OB*p9dNv7Kn|V>{X2$9Af{kL`4OAKRJsKDM*%eQf92``FI6_px1Q?_;~z-p6*S zy^rm3dmr1C_CB_&?R{+5+WXk9xA(E#XzydY+1|%?tG$oyc6%S&o%TMqyX}2!_uBi| z?zi``J!tP^d)VH`_Ncv&?Qwe_+mrS_wx{iVY|q;J*q*odvAt;TV|&@&$M&kdkL`7P zAKRPuKDM{*eQfXA``F&M_pyCw?_>Me-pBT-y^rm4dmr1E_CB_+?R{+D+WXkPxA(FA zXzyeD+1|(YtG$oycY7b(pY}eszwLc&|JwW5{&)AWG4}VdF@gvt5Wx&0SU?0Thycs7 zgIF9Of)hk=fe3C8!2=?AK?EO&;0F-`AVLsC2!RM;5Fr90L_vfYh!6)65+FhnL`Z=M zX%Ha;B4j~?9Egwy5egte5kx3~2xSnV0wPpFgc^uY2N4<|LK8%2fe397p#vgxL4+QN z&<7C)Ai@wt7=Z|55Mcr$OhJShh%g5c79heBL|B0cYY<@rB5Xl~9f+_85e^{25kxqF z2xk!C0wP>Ngd2!(2N511!V^Szfe3F9;R7OkL4+TO@COkAAR-V%1c8WP5D@|*LP10r zhzJJ}5g;NGL_~pzXb=$tB4R;A9EgYq5eXn75kw?`h-46v0wPjDL>h=l2N4+{A`?Vp qfrxAnkpm)fK|~&i$OjPxAfgaN6oH6h5K#gmN*VX}v6V4C(*XcbsAz2f diff --git a/shaders/triangle.frag b/shaders/triangle.frag index 859df85..19b75d0 100644 --- a/shaders/triangle.frag +++ b/shaders/triangle.frag @@ -15,13 +15,14 @@ layout(binding = 2) uniform sampler2D normal_tex; layout(location = 0) in vec2 tex_coords; layout(location = 1) in vec3 normal_wld; layout(location = 2) in vec3 position_wld; +layout(location = 3) in mat3 tbn; layout(location = 0) out vec4 out_color; void main() { -// vec3 normal_cam_u = normalize(normal_wld); // TODO vec3 normal_cam_u = texture(normal_tex, tex_coords).rgb; - normal_cam_u = normalize(normal_cam_u * 2.0 - 1.0); + normal_cam_u = normal_cam_u * 2.0 - 1.0; + normal_cam_u = normalize(tbn * normal_cam_u); vec3 light_direction_cam_u = normalize(ubo.light_position - position_wld); float ambient_strength = 0.1; diff --git a/shaders/triangle.vert b/shaders/triangle.vert index 145d379..875d44a 100644 --- a/shaders/triangle.vert +++ b/shaders/triangle.vert @@ -16,21 +16,35 @@ layout(binding = 0) uniform ObjectUniformData { layout(location = 0) in vec3 position; layout(location = 1) in vec2 uv; layout(location = 2) in vec3 normal; -layout(location = 3) in ivec4 bone_index; -layout(location = 4) in vec4 bone_weight; +layout(location = 3) in vec4 tangent; +layout(location = 4) in ivec4 bone_index; +layout(location = 5) in vec4 bone_weight; layout(location = 0) out vec2 tex_coords; layout(location = 1) out vec3 normal_wld; layout(location = 2) out vec3 position_wld; +layout(location = 3) out mat3 tbn; out gl_PerVertex { vec4 gl_Position; }; void main() { + // Vertex position gl_Position = ubo.projection * ubo.view * push.model * vec4(position, 1.0); + position_wld = vec3(push.model * vec4(position, 1.0)); + + // Just interpolate UV coords, no transformation needed tex_coords = uv; - position_wld = vec3(push.model * vec4(position, 1.0)); + // This should probably be in object space? idk normal_wld = vec3(mat3(transpose(inverse(push.model))) * normal); + + // Tangent->object space matrix + vec3 tangent3 = vec3(tangent.xy, 1.0); + vec3 bitangent = -cross(tangent3, normal_wld); + vec3 t = normalize(vec3(push.model * vec4(tangent3, 0.0))); + vec3 b = normalize(vec3(push.model * vec4(bitangent, 0.0))); + vec3 n = normalize(vec3(push.model * vec4(normal_wld, 0.0))); + tbn = mat3(t, b, n); } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c5c2d67..74b4b64 100644 --- a/src/main.rs +++ b/src/main.rs @@ -104,11 +104,11 @@ fn _matrix_vector_mul(matrix: &Matrix4, vector: &Vector3) -> Vector3 Result<(Vec, V let texture_index = primitive.material().pbr_metallic_roughness().base_color_texture().map(|tex_info| tex_info.texture().index()); let normal_map_index = primitive.material().normal_texture().map(|tex_info| tex_info.texture().index()); + let reader = primitive.reader(|buffer| Some(&buffers[buffer.index()])); let indices = reader.read_indices().ok_or(NoIndices)?; - let vertices_result = create_vertices(reader.read_positions(), reader.read_tex_coords(0), reader.read_normals(), reader.read_joints(0), reader.read_weights(0)); + let vertices_result = create_vertices( + reader.read_positions(), + reader.read_tex_coords(0), + reader.read_normals(), + reader.read_tangents(), + reader.read_joints(0), + reader.read_weights(0)); let vertices = vertices_result?; let cpu_mesh = CPUMesh { vertices, @@ -90,18 +98,21 @@ pub fn load_mesh(mesh_path: &str, print_status: bool) -> Result<(Vec, V fn create_vertices(positions: Option, tex_coords: Option, normals: Option, + tangents: Option, joints: Option, weights: Option) -> Result, String> { - match (positions, tex_coords, normals, joints, weights) { + match (positions, tex_coords, normals, tangents, joints, weights) { (Some(positions), Some(tex_coords), Some(normals), + Some(tangents), Some(joints), Some(weights)) => { Ok(positions .zip(tex_coords.into_f32()) .zip(normals) + .zip(tangents) .zip(joints.into_u16().map(|arr| { let mut casted_joints: [i32; 4] = [0; 4]; for i in 0..4 { @@ -110,10 +121,11 @@ fn create_vertices(positions: Option, casted_joints })) .zip(weights.into_f32()) - .map(|((((p, t), n), i), w)| Vertex { + .map(|(((((p, t), n), ta), i), w)| Vertex { position: p, uv: t, normal: n, + tangent: ta, bone_index: i, bone_weight: w }).collect()) @@ -121,22 +133,26 @@ fn create_vertices(positions: Option, (Some(positions), Some(tex_coords), Some(normals), + Some(tangents), None, None) => { Ok(positions .zip(tex_coords.into_f32()) .zip(normals) - .map(|((p, t), n)| Vertex { + .zip(tangents) + .map(|(((p, t), n), ta)| Vertex { position: p, uv: t, normal: n, + tangent: ta, bone_index: [-1; 4], bone_weight: [0.0; 4] }).collect()) }, - (None, _, _, _, _) => Err("Vertex positions missing!".to_string()), - (_, None, _, _, _) => Err("Tex coords missing!".to_string()), - (_, _, None, _, _) => Err("Normals missing!".to_string()), - (_, _, _, Some(_), None) => Err("Bone indices exist, but bone weights are missing!".to_string()), - (_, _, _, None, Some(_)) => Err("Bone weights exist, but bone incides are missing!".to_string()), + (None, _, _, _, _, _) => Err("Vertex positions missing!".to_string()), + (_, None, _, _, _, _) => Err("Tex coords missing!".to_string()), + (_, _, None, _, _, _) => Err("Normals missing!".to_string()), + (_, _, _, None, _, _) => Err("Tangents missing!".to_string()), + (_, _, _, _, Some(_), None) => Err("Bone indices exist, but bone weights are missing!".to_string()), + (_, _, _, _, None, Some(_)) => Err("Bone weights exist, but bone incides are missing!".to_string()), } } \ No newline at end of file diff --git a/src/vulkan.rs b/src/vulkan.rs index 5d33cad..4ea6993 100644 --- a/src/vulkan.rs +++ b/src/vulkan.rs @@ -30,8 +30,8 @@ use winit::window::{Window, WindowBuilder}; use line_vs::ty::LinePushConstants; use vs::ty::PushConstants; -use crate::mesh::CPUMesh; use crate::gameobject::{GameObject, GameObjectHandle}; +use crate::mesh::CPUMesh; const VALIDATION_LAYERS: &[&str] = &[ ]; @@ -41,10 +41,11 @@ pub struct Vertex { pub position: [f32; 3], pub uv: [f32; 2], pub normal: [f32; 3], + pub tangent: [f32; 4], pub bone_index: [i32; 4], pub bone_weight: [f32; 4], } -vulkano::impl_vertex!(Vertex, position, uv, normal, bone_index, bone_weight); +vulkano::impl_vertex!(Vertex, position, uv, normal, tangent, bone_index, bone_weight); #[derive(Default, Debug, Clone)] pub struct LinePoint {