fix: fall back to full precision UVs when the model has a very large UV layout

This commit is contained in:
Turánszki János
2024-12-30 12:13:17 +01:00
parent aa292dfaa7
commit 947bccf35f
3 changed files with 53 additions and 11 deletions
+34 -10
View File
@@ -769,6 +769,8 @@ namespace wi::scene
}
// Determine UV range for normalization:
size_t uv_stride = sizeof(Vertex_UVS);
Format uv_format = Vertex_UVS::FORMAT;
if (!vertex_uvset_0.empty() || !vertex_uvset_1.empty())
{
const XMFLOAT2* uv0_stream = vertex_uvset_0.empty() ? vertex_uvset_1.data() : vertex_uvset_0.data();
@@ -783,6 +785,13 @@ namespace wi::scene
uv_range_min = wi::math::Min(uv_range_min, uv0_stream[i]);
uv_range_min = wi::math::Min(uv_range_min, uv1_stream[i]);
}
if (std::abs(uv_range_max.x - uv_range_min.x) > 65536 || std::abs(uv_range_max.y - uv_range_min.y) > 65536)
{
// The bounding box of UVs is too large, fall back to full precision UVs:
uv_stride = sizeof(Vertex_UVS32);
uv_format = Vertex_UVS32::FORMAT;
}
}
const size_t position_stride = GetFormatStride(position_format);
@@ -809,7 +818,7 @@ namespace wi::scene
AlignTo(indices.size() * GetIndexStride(), alignment) +
AlignTo(vertex_normals.size() * sizeof(Vertex_NOR), alignment) +
AlignTo(vertex_tangents.size() * sizeof(Vertex_TAN), alignment) +
AlignTo(uv_count * sizeof(Vertex_UVS), alignment) +
AlignTo(uv_count * uv_stride, alignment) +
AlignTo(vertex_atlas.size() * sizeof(Vertex_TEX), alignment) +
AlignTo(vertex_colors.size() * sizeof(Vertex_COL), alignment) +
AlignTo(vertex_boneindices.size() * sizeof(Vertex_BON), alignment) +
@@ -1058,15 +1067,30 @@ namespace wi::scene
const XMFLOAT2* uv1_stream = vertex_uvset_1.empty() ? vertex_uvset_0.data() : vertex_uvset_1.data();
vb_uvs.offset = buffer_offset;
vb_uvs.size = uv_count * sizeof(Vertex_UVS);
Vertex_UVS* vertices = (Vertex_UVS*)(buffer_data + buffer_offset);
buffer_offset += AlignTo(vb_uvs.size, alignment);
for (size_t i = 0; i < uv_count; ++i)
vb_uvs.size = uv_count * uv_stride;
if (uv_stride == sizeof(Vertex_UVS))
{
Vertex_UVS vert;
vert.uv0.FromFULL(uv0_stream[i], uv_range_min, uv_range_max);
vert.uv1.FromFULL(uv1_stream[i], uv_range_min, uv_range_max);
std::memcpy(vertices + i, &vert, sizeof(vert));
Vertex_UVS* vertices = (Vertex_UVS*)(buffer_data + buffer_offset);
buffer_offset += AlignTo(vb_uvs.size, alignment);
for (size_t i = 0; i < uv_count; ++i)
{
Vertex_UVS vert;
vert.uv0.FromFULL(uv0_stream[i], uv_range_min, uv_range_max);
vert.uv1.FromFULL(uv1_stream[i], uv_range_min, uv_range_max);
std::memcpy(vertices + i, &vert, sizeof(vert));
}
}
else
{
Vertex_UVS32* vertices = (Vertex_UVS32*)(buffer_data + buffer_offset);
buffer_offset += AlignTo(vb_uvs.size, alignment);
for (size_t i = 0; i < uv_count; ++i)
{
Vertex_UVS32 vert;
vert.uv0.FromFULL(uv0_stream[i], uv_range_min, uv_range_max);
vert.uv1.FromFULL(uv1_stream[i], uv_range_min, uv_range_max);
std::memcpy(vertices + i, &vert, sizeof(vert));
}
}
}
@@ -1267,7 +1291,7 @@ namespace wi::scene
}
if (vb_uvs.IsValid())
{
vb_uvs.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_uvs.offset, vb_uvs.size, &Vertex_UVS::FORMAT);
vb_uvs.subresource_srv = device->CreateSubresource(&generalBuffer, SubresourceType::SRV, vb_uvs.offset, vb_uvs.size, &uv_format);
vb_uvs.descriptor_srv = device->GetDescriptorIndex(&generalBuffer, SubresourceType::SRV, vb_uvs.subresource_srv);
}
if (vb_atl.IsValid())