Uv greater than 1.0

new THREE.PlaneGeometry(1, 1)

I created a PlaneGeometry with a custom material

PlaneGeometry’s uv coordinates should all be between [0, 1], but I discard all pixels less than or equal to 1 in the shader, still showing a thin line at the edge

I can’t use clamp to keep it between 0-1, because the uv coordinates passed by this custom material may not be in the 0-1 range like plane.
what is the cause of this and how can I fix it
Thanks for any help!

Try <=0.0 || >=1.0 or <0.02 || >0.98

    if (uv.x > 1.0 || uv.y > 1.0 || uv.x < 0.0 || uv.y < 0.0) {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    else {

Shader accuracy problem?

if( fract( uv ) != uv ) discard;


Does it go away when you create the renderer with antialiasing turned off ?

1 Like

That was my next question. :wink:

1 Like

Yes, it is caused by anti-aliasing. Is there a solution to this situation

There are different solutions for different cases, most likely your case is not one of them. The solutions, that I’m aware of, are:

  • turn off renderer antialiasing, and use postprocessing antialiasing instead
  • convert (or treat) all values in [1,1+ε] → 1, and [-ε,0] → 0
  • modify your texture so that there are no issue with the border
  • shrink a bit the UV coordinates (either in the geometry or in the texture properties)

Can you make codepen example to test or archive

I’m not clear on the part where you said:

I discard all pixels less than or equal to 1 in the shader

but then said:

I can’t use clamp to keep it between 0-1

just one more attempt:

if( uv != fract( uv )) discard;
const float shrinkFactor = .95; //adjust this until edge artifacts go away...
uv = ((fract(uv)-.5)*shrinkFactor)+.5; //Shrink the UVs away from texture edge to avoid filtering/aa artifacts

Also if you could describe on a higher level what you’re trying to do, it might inform the approach like…
“I’m trying to allow users to place a decal on their model for clothing design”
or whatnot…

Another thing to look into/read about are the wrapping modes…(three.js docs)

You can use a decal with a transparent+black pixel border, and ClampToEdgeWrapping to place a smaller image somewhere on a larger mesh.

The artifact you’re seeing is because antialising hardware sometimes has to read samples outside of the UV coordinates to filter the fragments… the higher the aa setting, the more pixels outside the boundary it has to sample.
If you set the outer edge of pixels on your texture to black/transparent, the clamp to edge wrapping will repeat that transparent color value for the filtering.
I.e. instead of using discard… use a texture with a single black pixel border, and texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping
and texture.alphaTest = .1; // Alpha test is the non shader way to discard pixels below a certain alpha threshold.

I’m just thinking out loud though, take this all with a large grain of salt. :smiley: