From 2a3f48fd508a14cc0135044c1d0ad974a142692b Mon Sep 17 00:00:00 2001 From: Ivan Avdeev Date: Thu, 2 Nov 2023 13:47:31 -0400 Subject: [PATCH] vk: fix occasional inverted normal maps When texture coordinates are inverted, it makes tangent look into oppsite direction, which inverts TBN and therefore normal map. Make sure the tangent points to a consistent direction. Fixes #627 --- ref/vk/TODO.md | 3 ++- ref/vk/vk_brush.c | 28 ++++++++++++++++++++-------- ref/vk/vk_descriptor.c | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/ref/vk/TODO.md b/ref/vk/TODO.md index a864bfd6..cd82891c 100644 --- a/ref/vk/TODO.md +++ b/ref/vk/TODO.md @@ -1,7 +1,8 @@ # 2023-11-02 E323 - [x] lol meta: read and sort issues - [x] merge from upstream -- [ ] hevsuit glitches +- [x] hevsuit glitches +- [x] inverted normal map orientation - [ ] massage shaders: consolidate all bindings explicitly - [ ] skip sorting-by-texture when loading brush models (=> geometry count explosion; i.e. kusochki count will explode too) - [ ] kusochki-vs-materials diff --git a/ref/vk/vk_brush.c b/ref/vk/vk_brush.c index 1c5fc49e..19eadc46 100644 --- a/ref/vk/vk_brush.c +++ b/ref/vk/vk_brush.c @@ -1183,9 +1183,6 @@ static qboolean fillBrushSurfaces(fill_geometries_args_t args) { // FIXME make an explicit list of dynamic-uv geometries } - VectorCopy(surf->texinfo->vecs[0], tangent); - VectorNormalize(tangent); - vec3_t surf_normal; getSurfaceNormal(surf, surf_normal); @@ -1217,7 +1214,6 @@ static qboolean fillBrushSurfaces(fill_geometries_args_t args) { } float s_off = 0, t_off = 0; - float s_sc = 1, t_sc = 1; if (psurf && (psurf->flags & Patch_Surface_TexOffset)) { s_off = psurf->tex_offset[0]; @@ -1225,15 +1221,31 @@ static qboolean fillBrushSurfaces(fill_geometries_args_t args) { } if (psurf && (psurf->flags & Patch_Surface_TexScale)) { - s_sc = psurf->tex_scale[0]; - t_sc = psurf->tex_scale[1]; + svec[0] *= psurf->tex_scale[0]; + svec[1] *= psurf->tex_scale[0]; + svec[2] *= psurf->tex_scale[0]; + tvec[0] *= psurf->tex_scale[1]; + tvec[1] *= psurf->tex_scale[1]; + tvec[2] *= psurf->tex_scale[1]; } - const float s = s_off + s_sc * DotProduct( in_vertex->position, svec ) + svec[3]; - const float t = t_off + t_sc * DotProduct( in_vertex->position, tvec ) + tvec[3]; + const float s = s_off + DotProduct( in_vertex->position, svec ) + svec[3]; + const float t = t_off + DotProduct( in_vertex->position, tvec ) + tvec[3]; vertex.gl_tc[0] = s / surf->texinfo->texture->width; vertex.gl_tc[1] = t / surf->texinfo->texture->height; + + VectorCopy(svec, tangent); + VectorNormalize(tangent); + + // "Inverted" texture mapping should not lead to inverted tangent/normal map + // Make sure that orientation is preserved. + { + vec4_t stnorm; + CrossProduct(tvec, svec, stnorm); + if (DotProduct(stnorm, surf_normal) < 0.) + VectorNegate(tangent, tangent); + } } // lightmap texture coordinates diff --git a/ref/vk/vk_descriptor.c b/ref/vk/vk_descriptor.c index 4618916b..05ede5aa 100644 --- a/ref/vk/vk_descriptor.c +++ b/ref/vk/vk_descriptor.c @@ -173,7 +173,7 @@ void VK_DescriptorsCreate(vk_descriptors_t *desc) void VK_DescriptorsWrite(const vk_descriptors_t *desc, int set_slot) { - VkWriteDescriptorSet wds[16]; + VkWriteDescriptorSet wds[32]; ASSERT(ARRAYSIZE(wds) >= desc->num_bindings); for (int i = 0; i < desc->num_bindings; ++i){ const VkDescriptorSetLayoutBinding *binding = desc->bindings + i;