Browse Source

Sanitize tangents when creating mesh surfaces to avoid triggering the compressed mesh path in the shader

clayjohn 1 year ago
parent
commit
e3d31837eb

+ 5 - 0
scene/3d/sprite_3d.cpp

@@ -206,6 +206,11 @@ void SpriteBase3D::draw_texture_rect(Ref<Texture2D> 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;
 	}

+ 5 - 0
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;
 			}

+ 10 - 0
scene/resources/mesh.cpp

@@ -1156,6 +1156,11 @@ void _fix_array_compatibility(const Vector<uint8_t> &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<uint8_t> &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;
 					}

+ 12 - 0
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);
 						}
 					}