Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Texture Array mipmapping edge bleeding #48462

Closed
Lexpartizan opened this issue May 4, 2021 · 9 comments
Closed

Texture Array mipmapping edge bleeding #48462

Lexpartizan opened this issue May 4, 2021 · 9 comments

Comments

@Lexpartizan
Copy link

Godot version:

3.3 official.

OS/device including version:

Windows 10, Nvidia 1050, GLES3

Issue description:

I'm trying to use texture arrays, the description says that in the case of using texture array, mipmapping maps will be created separately for each section of the texture, which should eliminate artifacts. However, the video shows everything. When you try to tile, the edges of the tile just flicker terribly. And not only do they flow, but also my eyes.
https://youtu.be/OsROaOnfXBI

Steps to reproduce:
To do this, you need to repeat the texture of a specific tile in the texture array with mipmapping enabled. Without mipmapping, everything works correctly, however, I would like to use mipmapping for a variety of reasons.

Minimal reproduction project:

https://disk.yandex.ru/d/tXW0FuBhm6hMmw
There are two scenes, one with just a texture, the other with a texture array. Artifacts are the same with mipmapping enabled. However, in the case of just a texture, when filtering is enabled, white bars appear at the edges. This is normal behavior, as I found out. Texture array allows you to use filtering without restrictions.

In blender in eevee, there is no such problem, mipmapping works correctly, no artifacts, a beautiful image. However, you have to turn off the filtering, because there is no texture array and white strips appear.

Precisely because mipmapping works correctly in the blender in this case (and on the same texture), I think that there may be a problem in the engine.

PS. Perhaps this is related to this issue #27837
#27837
However, I should note that the resulting artifacts are not always white and that this problem is observed in the texture array. Which is specially designed to solve problems with mipmapping in such cases. But it doesn't solve it. However, at least it helps with filtering.

@clayjohn
Copy link
Member

clayjohn commented May 6, 2021

I'm not convinced that this is a mipmapping issue. From the video you posted, it looks more like a lighting/alignment issue rather than a mipmapping problem in the textures.

Can you please upload an MRP directly here instead of using a third party site? Github allows uploading zip files by dragging and dropping them into the text box. The reason I ask is that I am at work and our security settings don't allow me to download a 100+mb zip file from a Russian website.

@Calinou
Copy link
Member

Calinou commented May 6, 2021

Can you please upload an MRP directly here instead of using a third party site? Github allows uploading zip files by dragging and dropping them into the text box. The reason I ask is that I am at work and our security settings don't allow me to download a 100+mb zip file from a Russian website.

GitHub doesn't allow uploading ZIP files larger than 20 MB either 🙁

Here's the ZIP in OP reuploaded to 0x0: https://0x0.st/-BA1.zip (link expires in late 2021)

@clayjohn clayjohn added discussion and removed bug labels May 6, 2021
@clayjohn
Copy link
Member

clayjohn commented May 6, 2021

I have run the example project and identified the issue. The issue comes from two things:

  1. Your custom planemesh has improper UVs
  2. Your shader was zooming in on a section TextureArray and then force repeating.

When used properly, the TextureArray in your scene works fine. So, what do you need to do differently?

Use a mesh with proper UVs. UV's run from 0-1. When using a TextureArray each slice in the array is accessed as if it were a single texture (i.e. using the full range of UV coordinates). To access different slices you change the z value of the uv. A typical texture read looks like: ALBEDO = texture(tex_array, vec3(UV, slice_num)).rgb;. This doesn't work in your case because the UV is crafted to read from a small section of the UV, so you end up having to arbitrarily repeat the texture in shader (which breaks derivatives)

All I did was swap your ArrayMesh for a PlaneMesh and replace the calculation of uv1 with plain UV and all the artifacts disappeared.

@Lexpartizan
Copy link
Author

Lexpartizan commented May 7, 2021

@clayjohn I apologize for the delay in replying.
In general, the whole point of what I do is to achieve the repetition of the texture tile without the need to create extra geometry. It seems to me that the possibility of tiling in texture array would be very useful.
Yes, that's right, the artifacts are gone, as there is no repetition of the texture. By the way, even though the texture array has the repeat flag, its parts are not repeated.
And yet, artifacts also disappear if you turn off mipmapping. But there is no such problem in blender, and mipmapping works perfectly with the same shader even without texture array with simple texture. So I insist that mipmapping has problems.

@clayjohn
Copy link
Member

clayjohn commented May 7, 2021

If you want the texture to Tile, you can scale the UV's into a range greater than 0-1 with the repeat flag on. If you let the GPU handle the tiling for you, you won't get those artifacts.

To be clear, TextureArrays are implemented on the GPU. Godot has no control over how the mipmaps are calculated. It is completely the result of your code running directly on the hardware. If used properly, there won't be artifacts (as is the case if you do what I describe above)

The artifacts in your scene are the result of the texture() function having improper UV derivatives. texture() infers mipmaps based on the distance to the texture and the derivatives of the UV coordinates. This calculation is done in the hardware and Godot have no control over it. Your code introduces discontinuities into the UV coordinates which completely breaks the derivatives which leads to the hardware inferring improper mip maps.

@Lexpartizan
Copy link
Author

Lexpartizan commented May 7, 2021

@clayjohn
image

you can scale the UV's into a range greater than 0-1 with the repeat flag on
No, i cant.

@Lexpartizan
Copy link
Author

Lexpartizan commented May 7, 2021

Hmm, strange. I reloaded the Godot and the texture is now repeated. But if you uncheck repeat and put it back, it no longer works.

@Lexpartizan
Copy link
Author

Lexpartizan commented May 7, 2021

@clayjohn Thank you so much! You've really helped me move on!

@clayjohn
Copy link
Member

clayjohn commented May 7, 2021

To add to my comment above, the problematic part of your shader is the fract() call. It is what introduces the discontinuity.

I'm guessing you just forgot to hit "reimport" after setting the repeat flag on the texture.

Glad to hear it is working now! Good luck on your project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants