From e3d31837ebcc136f7b532e8ecfbbb8ee6eb665cc Mon Sep 17 00:00:00 2001 From: clayjohn Date: Wed, 11 Oct 2023 21:34:52 -0600 Subject: [PATCH] Sanitize tangents when creating mesh surfaces to avoid triggering the compressed mesh path in the shader --- scene/3d/sprite_3d.cpp | 5 +++++ scene/resources/immediate_mesh.cpp | 5 +++++ scene/resources/mesh.cpp | 10 ++++++++++ servers/rendering_server.cpp | 12 ++++++++++++ 4 files changed, 32 insertions(+) diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index e6404b57212..befabfe7b94 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -206,6 +206,11 @@ void SpriteBase3D::draw_texture_rect(Ref p_texture, Rect2 p_dst_rect, uint32_t value = 0; value |= (uint16_t)CLAMP(res.x * 65535, 0, 65535); value |= (uint16_t)CLAMP(res.y * 65535, 0, 65535) << 16; + if (value == 4294901760) { + // (1, 1) and (0, 1) decode to the same value, but (0, 1) messes with our compression detection. + // So we sanitize here. + value = 4294967295; + } v_tangent = value; } diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp index 0112ffd4522..3507df8bd88 100644 --- a/scene/resources/immediate_mesh.cpp +++ b/scene/resources/immediate_mesh.cpp @@ -208,6 +208,11 @@ void ImmediateMesh::surface_end() { uint32_t value = 0; value |= (uint16_t)CLAMP(t.x * 65535, 0, 65535); value |= (uint16_t)CLAMP(t.y * 65535, 0, 65535) << 16; + if (value == 4294901760) { + // (1, 1) and (0, 1) decode to the same value, but (0, 1) messes with our compression detection. + // So we sanitize here. + value = 4294967295; + } *tangent = value; } diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 971ec0e597e..3aeec7ea87a 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -1156,6 +1156,11 @@ void _fix_array_compatibility(const Vector &p_src, uint64_t p_old_forma uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_normal_tangent_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); + if (dst[0] == 0 && dst[1] == 65535) { + // (1, 1) and (0, 1) decode to the same value, but (0, 1) messes with our compression detection. + // So we sanitize here. + dst[0] = 65535; + } } src_offset += sizeof(uint8_t) * 4; } else { @@ -1167,6 +1172,11 @@ void _fix_array_compatibility(const Vector &p_src, uint64_t p_old_forma uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_normal_tangent_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); + if (dst[0] == 0 && dst[1] == 65535) { + // (1, 1) and (0, 1) decode to the same value, but (0, 1) messes with our compression detection. + // So we sanitize here. + dst[0] = 65535; + } } src_offset += sizeof(float) * 4; } diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index c5adb6cdf61..0ecfb6afb7c 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -612,6 +612,12 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint (uint16_t)CLAMP(res.y * 65535, 0, 65535), }; + if (vector[0] == 0 && vector[1] == 65535) { + // (1, 1) and (0, 1) decode to the same value, but (0, 1) messes with our compression detection. + // So we sanitize here. + vector[0] = 65535; + } + memcpy(&vw[p_offsets[ai] + i * p_normal_stride], vector, 4); } } else { // PACKED_FLOAT64_ARRAY @@ -627,6 +633,12 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint (uint16_t)CLAMP(res.y * 65535, 0, 65535), }; + if (vector[0] == 0 && vector[1] == 65535) { + // (1, 1) and (0, 1) decode to the same value, but (0, 1) messes with our compression detection. + // So we sanitize here. + vector[0] = 65535; + } + memcpy(&vw[p_offsets[ai] + i * p_normal_stride], vector, 4); } }