-
Notifications
You must be signed in to change notification settings - Fork 126
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
Colormap artifact in mipmaps along region boundaries #284
Comments
I reopened this because I think this is an upstream bug in In short, I've encountered an artifact on mipmapped texture array lookups. The problem exists with To test it:
At the bottom of the shader you'll see four sections:
With (2) enabled, you'll see the artifact along the path at the region borders, shown in the red artifact below. The green artifact is unrelated, tracked in #185. Here is where mipmaps are created on the colormap texture array: Terrain3D/src/terrain_3d_storage.cpp Line 239 in 7860ecf
|
@TokisanGames I intend to take a look a bit more closely later, but here are the first two things I will look for:
My gut is leaning towards this being an issue with the derivative. When using custom UV coordinates that are computed in the shader you pretty much always have to calculate the derivative yourself and then use |
Thanks for looking at this @clayjohn
Hmm, I understand. However here, if I change floor to round in get_region_uv/2 it breaks the terrain. Every other region is messed up.
I haven't studied derivatives in over 20 years, and never in the context of shaders. Do you have a link where I can learn what I need? I've found it hard to find anything that is not arcane phonebook information on textureQueryLod, texturelod, texturegrad, etc. I found some links in reference below I'm looking at. We used to use textureGrad (see update 3) on the ground texture arrays. But I found that using I don't want to pay 20% to switch to textureGrad for the colormap. I'd rather use the current hacky method of clamping I'm not really sure what to do. Reference |
Ben Golus has a detailed medium article discussing ways to deal with this same issue https://bgolus.medium.com/distinctive-derivative-differences-cce38d36797b. I don't really have any definitive resources to learn about derivatives though. Manual derivatives tend to be slow compared to the automatically calculated ones as the automatically calculated ones are often done in hardware and/or with a bunch of GPU-specific tricks. So I'm not surprised that manually calculating them ended up being a bit slower. 20% seems like a lot, but I guess it depends on what your results are, if you end up with much lower LODs, the shader can become way more expensive. Basically what you need is a good way of approximating the per-pixel change in your UV channel without the discontinuities introduced by Accordingly, the easy workaround is to do the following:
Testing locally I can confirm that in the "problem 1" case the artifacts go away when using UV2 instead of region_uv. However, I can't reproduce the issue when using any of the other "problems" or when using actual color. |
Terrain3D version
v0.9.0
System information
Godot v4.1.3.stable - Windows 10.0.22621 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3070 Laptop GPU (NVIDIA; 31.0.15.4633) - 12th Gen Intel(R) Core(TM) i9-12900H (20 Threads)
Is the issue reproducable in the demo?
Yes
Issue description
Mipmaps were generated on the colormap array in 7e4f9eb to avoid distant noise, which was very obvious when using a full colormap such as in GIS applications w/ satellite photos (farther below). However, this has introduced another artifact on the region boundary. Enabling
renormalize
ongenerate_mipmaps()
has no affect.ALBEDO=colormap*vec3(.1)
Regular shader
Though mipmaps should be generated on the whole map at once, it appears this tiling is not a problem and the individual mipmaps blend together fine. It's actually surprising that they blend at all, given how different from each other the lower lods look.
The only artifact is the small grid line that shows up when up close on mipmap0 shown at the start, and also far away shown here.
Upon further testing, I've found that indeed it is not the mipmap lods, it is actually the system that determines which LOD to use that is the problem.
These lines are the borders of the individual textures in the arrays and show up when using
texture()
.I have found I can clamp the lod based on distance.
I could go up to 2048 or 3172 to basically eliminate the grid at all distances. However in practice with either a full GIS colormap, or ground textures up close, 1024 gives me the best results of texture mipmaping to eliminate noise at far distances, and fix this line at close distances.
I'll close this issue with this workaround, though I believe this to be an engine bug as
textureQueryLod()
should not show a grid and should not bleed into my renders usingtexture()
.textureLod(tex, 0)
does not include this grid artifact.Basically these two lookup blocks provide very similar results. It's as if when
texture()
is used on texture arrays, it adds the results oftextureQueryLod()
to the result.Upstream issues
godotengine/godot#48462
godotengine/godot#27837 (comment)
godotengine/godot#33519
The text was updated successfully, but these errors were encountered: