Artifacts Found When Tiling UVs with Clamp Sample & Frac

Here’s I’m trying to tile UVs and apply some random rotation for those tiles. In order to do that, I need to tile UVs with the frac node. And I need to use the texture sampling with the Clamp mode.

As you can see, now there are some artifacts around the border of the texture.

I got this fixed using by sending custom Mip Levels like this:

But still, I’d like to see the reason behind this.

Toss in a ceil node instead of the fract node.
if you set a box as the preview and zoom in you’ll see that the line is actually a small fraction of the image repeating over and over.

My guess is that it’s actually a mip artifact due to floating point precision of frac.
Probably should be reported as a bug really.
it seems that it is ignoring at least a range from .001 to .01

Not sure how to test this. Would actually be cool to be able to get a step by step result of every operation call logged somewhere to review what numbers FRAC is cutting

I got this for both ceil & floor as well. See:

So, this shouldn’t be something with frac.

May be it’s something with Anisotropic Filtering:

I just tested on 4.24 as well. I get the same result.
May be that’s how it is from the beginning.
Anyway, I will do a bug report.

This has been an issue for as long as I can remember. It’s extremely bad with world projected UVs; If the edges of a face line up right with the edge of a tile, you’ll get what looks like z-fighting. I posted about this in this thread 6 months ago, and encouraged another user to report it as a bug.

Unfortunately Epic’s bug reporting process ensures the community will have virtually no idea if this is a bug, if it will ever be fixed, or if they’re even aware of it.

2 Likes

In case you’re curious this problem is also present in all light functions applied to point lights. I’m guessing whatever they’re doing to create the equirectangular projection probably involves using frac/ceil/floor.

1 Like

the reason frac does this is due to the continuous nature of UVs.
think of UVs like a continuous field of values, going 0->1->2->N, and interpolating the values in between.
“zoom in” and you’d see something like 0->0.25->0.5->0.75->1.0->1.25. zoom in closer to 1.0 and you’d see something like 0.98->0.99->1.0->1.1
now the moment you do frac you’re actually making it do 0.98->0.99->0.0->0.1, which means that in the span from 0.999999 to 0.0 due to its continuous nature it has to wrap around back and interpolate all values from 0.999999 back down to zero, which happens in the span of a single pixel.
what you see in the artifact area is a UV warping artifact. the entire texture is warp-squashed into a single pixel

I’m sure someone can find a more eloquent way to explain it but in [not so] short that’s the reason UV’s can’t just have cuts or jumps. and it doesn’t matter if you use frac, ceil, round, floor, if, etc. anything that causes a hard discontinuity in the field of values will cause a single-pixel UV warping artifact, similar to how using lerp on UVs will cause a UV warping artifact (just on a larger area)

a common workaround is to use the Derivative mipvalue mode. simply plug DDX and DDY nodes to your UVs and plug them to the derivative inputs of the texture sampler

5 Likes

Thank you so much for the explanation man, this problem has been a thorn in my side for a long time.

1 Like

Thanks. I think that’s exactly what ComputeMipLevel function does.

Thanks for the explanation.