Here I have the UV mab for an .obj file:
In three.js:

As you can see, this out-of-bounds faces are colored as black. How can I instead have them become transparent? (It is not an option to put them in-bounds with a transparent area of the texture)
Here I have the UV mab for an .obj file:
As you can see, this out-of-bounds faces are colored as black. How can I instead have them become transparent? (It is not an option to put them in-bounds with a transparent area of the texture)
UV maps have no in-bounds or out-of-bounds areas. Every pixel of them could be (and will be) used as a texture when some UV coordinates point to them.
If you do not want to use alpha maps (as this is the default way to have texture-base transparency), you might consider customizing the fragment shader to discard fragments (pixels) that fall in the out-of-bounds area. For this, you also have to implement a way for the shader to distinguish what is in and what it out either by filtering the UV coordinates, or by filtering the color from the texture.
I might have misunderstood your question. If this is the case, I’m sorry.
The default behavior of Three.js is to pick whatever color is in the image, and use that. So, to have custom behavior, I believe that the only options are to
onBeforeCompile
, a callback in which you can modify the shader string before it will be compiled into the GPU program)wgslFn
are used for providing WebGPU WGSL shader code to Three.js)In all three cases, what you will need for the bit of custom logic is to change the fragment output color (gl_FragColor
or out
variable) based on some logic. Pseudo code:
if (gl_FragColor == black) {
gl_FragColor = vec4(0, 0, 0, 0); // zero alpha (transparent) or whatever color you want instead
// or
discard; // don't draw the pixel
} else {
gl_FragColor = ... same code as before ...
}
In my case, I want to discard anything outside the image bounds (anything beyond (0,1) for either U and V. Note that in the OP anything inside the UV (any values less than 1) are not out of bounds of the image. In the OP case, there isn’t anything special about picking the color black (it is just a color) so special meaning has to be given to that (f.e. with custom injected shader code). So in my case, I might do this:
if (uv.x > 1 || uv.y > 1) {
discard; // don't draw the pixel
} else {
gl_FragColor = ... same code as before ...
}
(This is how answers can be written more helpfully, which I hope more people can do. Sorry that you didn’t get this until 2 years later @h_hh!)
Maybe
if(max(abs(uv.x - 0.5), abs(uv.y - 0.5)) > 0.5) discard;
or
if(uv.x < 0 || uv.y < 0 || uv.x > 1 || uv.y > 1) discard;
or
if(min(uv.x, uv.y) < 0 || max(uv.x, uv.y) > 1) discard;
I would go with this one:
The more comparison operations in a line, the better
Expanding on the suggestion from @Chaser_Code – note that mipmaps (if enabled) need to be considered. When viewed at a distance or at an angle, three.js samples from a lower-resolution copy of the image. With UVs right at the edge of the colored area, and no padding/dilation in the texture, you might be sampling from the intended colors mixed with black.