Fix multiple issues with UV compression
This commit is contained in:
parent
9144457484
commit
3f5c16dd9e
6 changed files with 39 additions and 13 deletions
|
@ -92,7 +92,7 @@
|
|||
<return type="Array" />
|
||||
<param index="0" name="surface_idx" type="int" />
|
||||
<description>
|
||||
Returns the arrays for the vertices, normals, uvs, etc. that make up the requested surface. See [method add_surface].
|
||||
Returns the arrays for the vertices, normals, UVs, etc. that make up the requested surface. See [method add_surface].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_surface_blend_shape_arrays" qualifiers="const">
|
||||
|
|
|
@ -366,6 +366,9 @@
|
|||
<constant name="ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY" value="268435456" enum="ArrayFormat" is_bitfield="true">
|
||||
Flag used to mark that the mesh intentionally contains no vertex array.
|
||||
</constant>
|
||||
<constant name="ARRAY_FLAG_COMPRESS_ATTRIBUTES" value="536870912" enum="ArrayFormat" is_bitfield="true">
|
||||
Flag used to mark that a mesh is using compressed attributes (vertices, normals, tangents, UVs). When this form of compression is enabled, vertex positions will be packed into an RGBA16UNORM attribute and scaled in the vertex shader. The normal and tangent will be packed into an RG16UNORM representing an axis, and a 16-bit float stored in the A-channel of the vertex. UVs will use 16-bit normalized floats instead of full 32-bit signed floats. When using this compression mode you must use either vertices, normals, and tangents or only vertices. You cannot use normals without tangents. Importers will automatically enable this compression if they can.
|
||||
</constant>
|
||||
<constant name="BLEND_SHAPE_MODE_NORMALIZED" value="0" enum="BlendShapeMode">
|
||||
Blend shapes are normalized.
|
||||
</constant>
|
||||
|
|
|
@ -4226,7 +4226,7 @@
|
|||
Flag used to mark that the mesh does not have a vertex array and instead will infer vertex positions in the shader using indices and other information.
|
||||
</constant>
|
||||
<constant name="ARRAY_FLAG_COMPRESS_ATTRIBUTES" value="536870912" enum="ArrayFormat" is_bitfield="true">
|
||||
Flag used to mark that a mesh is using compressed attributes (vertices, normals, tangents, uvs). When this form of compression is enabled, vertex positions will be packed into into an RGBA16UNORM attribute and scaled in the vertex shader. The normal and tangent will be packed into a RG16UNORM representing an axis, and an 16 bit float stored in the A-channel of the vertex. UVs will use 16-bit normalized floats instead of full 32 bit signed floats. When using this compression mode you must either use vertices, normals, and tangents or only vertices. You cannot use normals without tangents. Importers will automatically enable this compression if they can.
|
||||
Flag used to mark that a mesh is using compressed attributes (vertices, normals, tangents, UVs). When this form of compression is enabled, vertex positions will be packed into an RGBA16UNORM attribute and scaled in the vertex shader. The normal and tangent will be packed into an RG16UNORM representing an axis, and a 16-bit float stored in the A-channel of the vertex. UVs will use 16-bit normalized floats instead of full 32-bit signed floats. When using this compression mode you must use either vertices, normals, and tangents or only vertices. You cannot use normals without tangents. Importers will automatically enable this compression if they can.
|
||||
</constant>
|
||||
<constant name="ARRAY_FLAG_FORMAT_VERSION_BASE" value="35" enum="ArrayFormat" is_bitfield="true">
|
||||
Flag used to mark the start of the bits used to store the mesh version.
|
||||
|
|
|
@ -870,6 +870,8 @@ void Mesh::_bind_methods() {
|
|||
BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_8_BONE_WEIGHTS);
|
||||
BIND_BITFIELD_FLAG(ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY);
|
||||
|
||||
BIND_BITFIELD_FLAG(ARRAY_FLAG_COMPRESS_ATTRIBUTES);
|
||||
|
||||
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
|
||||
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
|
||||
|
||||
|
|
|
@ -400,7 +400,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
|
|||
max_val = max_val.abs().max(min_val.abs());
|
||||
max_val2 = max_val2.abs().max(min_val2.abs());
|
||||
|
||||
r_uv_scale = Vector4(max_val.x, max_val.y, max_val2.x, max_val2.y) * Vector4(2.0, 2.0, 2.0, 2.0);
|
||||
if (min_val.x >= 0.0 && min_val2.x >= 0.0 && max_val.x <= 1.0 && max_val2.x <= 1.0 &&
|
||||
min_val.y >= 0.0 && min_val2.y >= 0.0 && max_val.y <= 1.0 && max_val2.y <= 1.0) {
|
||||
// When all channels are in the 0-1 range, we will compress to 16-bit without scaling to
|
||||
// preserve the bits as best as possible.
|
||||
r_uv_scale = Vector4(0.0, 0.0, 0.0, 0.0);
|
||||
} else {
|
||||
r_uv_scale = Vector4(max_val.x, max_val.y, max_val2.x, max_val2.y) * Vector4(2.0, 2.0, 2.0, 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int ai = 0; ai < RS::ARRAY_MAX; ai++) {
|
||||
|
@ -670,8 +677,11 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
|
|||
if (p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
|
||||
for (int i = 0; i < p_vertex_array_len; i++) {
|
||||
Vector2 vec = src[i];
|
||||
// Normalize into 0-1 from possible range -uv_scale - uv_scale.
|
||||
vec = vec / (Vector2(r_uv_scale.x, r_uv_scale.y)) + Vector2(0.5, 0.5);
|
||||
if (!r_uv_scale.is_zero_approx()) {
|
||||
// Normalize into 0-1 from possible range -uv_scale - uv_scale.
|
||||
vec = vec / (Vector2(r_uv_scale.x, r_uv_scale.y)) + Vector2(0.5, 0.5);
|
||||
}
|
||||
|
||||
uint16_t uv[2] = { (uint16_t)CLAMP(vec.x * 65535, 0, 65535), (uint16_t)CLAMP(vec.y * 65535, 0, 65535) };
|
||||
memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], uv, 4);
|
||||
}
|
||||
|
@ -695,8 +705,10 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
|
|||
if (p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
|
||||
for (int i = 0; i < p_vertex_array_len; i++) {
|
||||
Vector2 vec = src[i];
|
||||
// Normalize into 0-1 from possible range -uv_scale - uv_scale.
|
||||
vec = vec / (Vector2(r_uv_scale.z, r_uv_scale.w)) + Vector2(0.5, 0.5);
|
||||
if (!r_uv_scale.is_zero_approx()) {
|
||||
// Normalize into 0-1 from possible range -uv_scale - uv_scale.
|
||||
vec = vec / (Vector2(r_uv_scale.z, r_uv_scale.w)) + Vector2(0.5, 0.5);
|
||||
}
|
||||
uint16_t uv[2] = { (uint16_t)CLAMP(vec.x * 65535, 0, 65535), (uint16_t)CLAMP(vec.y * 65535, 0, 65535) };
|
||||
memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], uv, 4);
|
||||
}
|
||||
|
@ -1311,7 +1323,7 @@ void RenderingServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_p
|
|||
mesh_add_surface(p_mesh, sd);
|
||||
}
|
||||
|
||||
Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb) const {
|
||||
Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb, const Vector4 &p_uv_scale) const {
|
||||
uint32_t offsets[RS::ARRAY_MAX];
|
||||
|
||||
uint32_t vertex_elem_size;
|
||||
|
@ -1469,7 +1481,12 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t
|
|||
if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
|
||||
for (int j = 0; j < p_vertex_len; j++) {
|
||||
const uint16_t *v = reinterpret_cast<const uint16_t *>(&ar[j * attrib_elem_size + offsets[i]]);
|
||||
w[j] = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
|
||||
Vector2 vec = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
|
||||
if (!p_uv_scale.is_zero_approx()) {
|
||||
vec = (vec - Vector2(0.5, 0.5)) * Vector2(p_uv_scale.x, p_uv_scale.y);
|
||||
}
|
||||
|
||||
w[j] = vec;
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < p_vertex_len; j++) {
|
||||
|
@ -1489,7 +1506,11 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t
|
|||
if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
|
||||
for (int j = 0; j < p_vertex_len; j++) {
|
||||
const uint16_t *v = reinterpret_cast<const uint16_t *>(&ar[j * attrib_elem_size + offsets[i]]);
|
||||
w[j] = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
|
||||
Vector2 vec = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
|
||||
if (!p_uv_scale.is_zero_approx()) {
|
||||
vec = (vec - Vector2(0.5, 0.5)) * Vector2(p_uv_scale.z, p_uv_scale.w);
|
||||
}
|
||||
w[j] = vec;
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < p_vertex_len; j++) {
|
||||
|
@ -1686,7 +1707,7 @@ TypedArray<Array> RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mes
|
|||
for (uint32_t i = 0; i < blend_shape_count; i++) {
|
||||
Vector<uint8_t> bs_data = blend_shape_data.slice(i * divisor, (i + 1) * divisor);
|
||||
Vector<uint8_t> unused;
|
||||
blend_shape_array.set(i, _get_array_from_surface(bs_format, bs_data, unused, unused, sd.vertex_count, unused, 0, sd.aabb));
|
||||
blend_shape_array.set(i, _get_array_from_surface(bs_format, bs_data, unused, unused, sd.vertex_count, unused, 0, sd.aabb, sd.uv_scale));
|
||||
}
|
||||
|
||||
return blend_shape_array;
|
||||
|
@ -1708,7 +1729,7 @@ Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p
|
|||
|
||||
uint64_t format = p_data.format;
|
||||
|
||||
return _get_array_from_surface(format, vertex_data, attrib_data, skin_data, vertex_len, index_data, index_len, p_data.aabb);
|
||||
return _get_array_from_surface(format, vertex_data, attrib_data, skin_data, vertex_len, index_data, index_len, p_data.aabb, p_data.uv_scale);
|
||||
}
|
||||
#if 0
|
||||
Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const {
|
||||
|
|
|
@ -52,7 +52,7 @@ class RenderingServer : public Object {
|
|||
int mm_policy = 0;
|
||||
bool render_loop_enabled = true;
|
||||
|
||||
Array _get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb) const;
|
||||
Array _get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb, const Vector4 &p_uv_scale) const;
|
||||
|
||||
const Vector2 SMALL_VEC2 = Vector2(CMP_EPSILON, CMP_EPSILON);
|
||||
const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON);
|
||||
|
|
Loading…
Reference in a new issue