Browse Source

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.
master
Nico de Poel 3 years ago
parent
commit
552678f67c
  1. 24
      tesselate.cpp

24
tesselate.cpp

@ -42,8 +42,8 @@ std::vector<Tesselator::Polygon> Tesselator::tesselateFace(const face_t* face)
// Transform the vertex to texture space and calculate the texture UV bounds // Transform the vertex to texture space and calculate the texture UV bounds
Vec3 st = textureTrsf.TransformPoint(vertexPoint); 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 }; contour.vertex[edgeListIdx] = gpc_vertex{ st.x, st.y };
} }
@ -58,11 +58,19 @@ std::vector<Tesselator::Polygon> 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 // 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 // Create a square polygon that covers the entire cell
gpc_polygon cell = { 0 }; gpc_polygon cell = { 0 };
@ -70,9 +78,9 @@ std::vector<Tesselator::Polygon> Tesselator::tesselateFace(const face_t* face)
cell_bounds.num_vertices = 4; cell_bounds.num_vertices = 4;
cell_bounds.vertex = (gpc_vertex*)malloc(4 * sizeof(gpc_vertex)); cell_bounds.vertex = (gpc_vertex*)malloc(4 * sizeof(gpc_vertex));
cell_bounds.vertex[0] = gpc_vertex{ x, y }; 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); gpc_add_contour(&cell, &cell_bounds, 0);
// Take the intersection to get the chunk of the face that's inside this cell // Take the intersection to get the chunk of the face that's inside this cell

Loading…
Cancel
Save