From 552678f67cb616aa839fd32a9d74457688b28898 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Tue, 14 Feb 2023 16:12:31 +0100 Subject: [PATCH] Reduced amount of geometry artifacting from T-junctions by rounding repeating UVs down to a grid that will be shared by adjacent faces using the same textures. Sacrifices some performance again, but makes both geometry and lighting look a lot more solid. --- tesselate.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tesselate.cpp b/tesselate.cpp index bb9c4c1..af74bea 100644 --- a/tesselate.cpp +++ b/tesselate.cpp @@ -42,8 +42,8 @@ std::vector Tesselator::tesselateFace(const face_t* face) // Transform the vertex to texture space and calculate the texture UV bounds Vec3 st = textureTrsf.TransformPoint(vertexPoint); - if (st.x > maxS) maxS = st.x; if (st.x < minS) minS = st.x; - if (st.y > maxT) maxT = st.y; if (st.y < minT) minT = st.y; + if (st.x > maxS) maxS = ceil(st.x); if (st.x < minS) minS = floor(st.x); + if (st.y > maxT) maxT = ceil(st.y); if (st.y < minT) minT = floor(st.y); contour.vertex[edgeListIdx] = gpc_vertex{ st.x, st.y }; } @@ -58,11 +58,19 @@ std::vector Tesselator::tesselateFace(const face_t* face) } // Create a virtual grid at the texture bounds and iterate over each cell to break up the face into repeating tiles - double cellSize = texture_isRepeatable(miptex) ? 2.0 : 1.0; + double cellWidth = 1.0, cellHeight = 1.0; + if (texture_isRepeatable(miptex)) + { + cellWidth = cellHeight = 2.0; + + // Snap minS and minT to a grid of cellWidth/Height cell sizes, to avoid creating lots of T-junctions between adjacent faces + minS = floor(minS / cellWidth) * cellWidth; + minT = floor(minT / cellHeight) * cellHeight; + } - for (double y = floor(minT); y <= ceil(maxT); y += cellSize) + for (double y = minT; y < maxT; y += cellHeight) { - for (double x = floor(minS); x <= ceil(maxS); x += cellSize) + for (double x = minS; x < maxS; x += cellWidth) { // Create a square polygon that covers the entire cell gpc_polygon cell = { 0 }; @@ -70,9 +78,9 @@ std::vector Tesselator::tesselateFace(const face_t* face) cell_bounds.num_vertices = 4; cell_bounds.vertex = (gpc_vertex*)malloc(4 * sizeof(gpc_vertex)); cell_bounds.vertex[0] = gpc_vertex{ x, y }; - cell_bounds.vertex[1] = gpc_vertex{ x, y + cellSize }; - cell_bounds.vertex[2] = gpc_vertex{ x + cellSize, y + cellSize }; - cell_bounds.vertex[3] = gpc_vertex{ x + cellSize, y }; + cell_bounds.vertex[1] = gpc_vertex{ x, y + cellHeight }; + cell_bounds.vertex[2] = gpc_vertex{ x + cellWidth, y + cellHeight }; + cell_bounds.vertex[3] = gpc_vertex{ x + cellWidth, y }; gpc_add_contour(&cell, &cell_bounds, 0); // Take the intersection to get the chunk of the face that's inside this cell