Visual artifact at poles of UV sphere (gltf format)

I am creating a gltf model in Blender, where I have applied the following texture to a sphere:

After UV mapping and exporting in gltf format, the two black bands render as black dots in panda3d, as expected. Except they exhibit weird visual artifacts:

ts1
ts2

The equatorial black dots render as expected.

Does anyone have a solution for this? I don’t care if it’s hacky.

cue.blend (1.0 MB)
cue.glb (476.2 KB)

Cheers,
Evan

The artefacts appear when you zoom out, so my first guess would be a mimap problem : either it’s not enabled on the mesh, or the generated mimap is not optimum for your spherical projection.

What is a mimap? I think it has to do with vertex density–because it is a UV sphere it has a very high density of points at the pole. When I turn down the vertex density it seems a little better.

Sorry, I meant miPmap, the autocorrect replaced it :slight_smile:

Mipmaps are scaled down versions of a texture that are used to avoid aliasing or artefact when a texture, mapped on a mesh, is seen from far away.

What happens of you instead use an Ico-Sphere, and adapt your texture to the unwrapped form of that?

My thinking is that, if this is some sort of (possibly-mip-mapping-related) issue caused by the narrow triangles at the poles, and their likely-stretched UVs, then perhaps one solution is to use a type of sphere lacks that feature.

(As a further safeguard, I might suggest using the “Smart UV Project” UV-mapping tool, if your version of Blender has it. The resulting map–as generated on my machine, at least–is more awkward to work with, but doesn’t seem to have any stretched triangles.)

Sorry, I meant miPmap, the autocorrect replaced it :slight_smile:

Mipmaps are scaled down versions of a texture that are used to avoid aliasing or artefact when a texture, mapped on a mesh, is seen from far away.

Yeah, that makes sense. Well it seemed like mipmap was enabled on my mesh, and I turned it off according to these instructions, but it had no effect.

What happens of you instead use an Ico-Sphere, and adapt your texture to the unwrapped form of that?

My thinking is that, if this is some sort of (possibly-mip-mapping-related) issue caused by the narrow triangles at the poles, and their likely-stretched UVs, then perhaps one solution is to use a type of sphere lacks that feature.

I’m almost sure that would fix the problem, since there would be no near-discontinuity at that point. Do you know how I can convert my texture image to an ico-sphere format?

(As a further safeguard, I might suggest using the “Smart UV Project” UV-mapping tool, if your version of Blender has it. The resulting map–as generated on my machine, at least–is more awkward to work with, but doesn’t seem to have any stretched triangles.)

For me, it seems to have the same stretched triangles at the poles.

Not an automatic method, I fear–especially as the process would presumably depend on the mapping that you chose.

Ah, sorry, I perhaps wrote ambiguously–I meant to indicate “Smart UV Project” being applied to the ico-sphere, not the current UV-sphere. ^^;

Ok thank you guys. I’m going to mark your suggestion to use an ico-sphere as the solution, since that would definitely get rid of the pole effect. I may try and manually adapt my texture image to an ico-sphere UV projection, but for the time being I’m simply going to remove the dots at the poles. Thanks.

1 Like

It seems that the issue is indeed related to mipmapping, as suggested by @eldee .
Specifically, the texture filter type used when viewing the texture from afar (“texture minification”) is set to FT_nearest_mipmap_linear. Setting it to the default FT_linear seems to fix the problem:

model = base.loader.load_model("cue.glb")
model.reparent_to(base.render)
tex = model.find_texture("cue")
tex.set_minfilter(SamplerState.FT_linear)

When in doubt, you can always print out a Texture to see its attributes:

print(tex)

which outputs:

2d_texture cue
2-d, 2569 x 1280 pixels, each 4 bytes, srgb_alpha
sampler wrap(u=repeat, v=repeat, w=repeat, border=0 0 0 1) filter(min=nearest_mipmap_linear, mag=linear, aniso=0) lod(min=-1000, max=1000, bias=0) 13153280 bytes in ram, compression off

3 Likes

This is great Epihaius. Thanks so much for solving the issue and teaching me something along the way.

3 Likes