Godot Version
Godot v4.4.1 stable mono
Question
My problem is I am creating a texture atlas dynamically and applying the atlas to a shader in which I calculate the correct UV for the selected texture id which works great, but when I start zooming out the texture edges start disappearing. As far as I know the reason for it is because my textures are 64x64 px big and when I reach a point there is not enough pixels to scan so the edges disappear. But this is not ideal obviously. Is there any workaround for this?
My setup is like this:
I have a CanvasLayer for the MultiMeshInstance2Ds which have the materials with the shaders, and the Camera is also attached to this CanvasLayer. The layer is set to Follow the viewport.
My shader code is this:
shader_type canvas_item;
uniform sampler2D atlas : filter_nearest, repeat_disable;
uniform vec2 tile_size;
varying float tile_x;
varying float tile_y;
varying float is_preview;
void vertex()
{
int b = int(INSTANCE_CUSTOM.b * 255.0);
tile_x = INSTANCE_CUSTOM.r * 255.0;
tile_y = INSTANCE_CUSTOM.g * 255.0;
is_preview = float((b >> 0) & 1);
}
void fragment()
{
vec2 tile_offset = vec2(tile_x, tile_y) * tile_size;
vec2 tile_uv = tile_offset + vec2(UV.x, 1.0 - UV.y) * tile_size;
vec4 tex = texture(atlas, tile_uv);
// Some color adjustment if the object is preview or not
COLOR = tex;
}
Some examples how does it look, inside the red rectangle are the zoomed out, looking bad textures and on the right inside the green one the correct one.
Honestly any help would be appreciated, because I’m very close to giving up on my whole project if I can’t solve this problem, because I cannot work with this bottleneck, I’m very lost.
Additional information: I create no mipmaps for the texture atlas, I import the images/textures as Image in png format. Here is my code for creating the texture atlas:
internal ImageTexture CreateTextureAtlas(List<Image> textures, Dictionary<string, int> indexTextureDictonary)
{
int rowsNeeded = Mathf.CeilToInt((float)textures.Count / GameTextureManager.TILES_PER_ROW);
int atlasHeight = rowsNeeded * GenerationSettings.PIXELS_PER_TILE;
Image atlasImage = Image.CreateEmpty(GameTextureManager.TEXTURE_ATLAS_SIZE, atlasHeight, false, Image.Format.Rgba8);
atlasImage.Fill(new Color(0, 0, 0, 0));
int index = 0;
foreach (KeyValuePair<string, int> keyValuePair in indexTextureDictonary)
{
if (index >= textures.Count)
break;
int tileX = index % GameTextureManager.TILES_PER_ROW;
int tileY = index / GameTextureManager.TILES_PER_ROW;
Rect2I destRect = new Rect2I(tileX * GenerationSettings.PIXELS_PER_TILE,
tileY * GenerationSettings.PIXELS_PER_TILE,
GenerationSettings.PIXELS_PER_TILE,
GenerationSettings.PIXELS_PER_TILE);
Rect2I srcRect = new Rect2I(0,
0,
GenerationSettings.PIXELS_PER_TILE,
GenerationSettings.PIXELS_PER_TILE);
atlasImage.BlitRect(textures[index], srcRect, destRect.Position);
index++;
}
return ImageTexture.CreateFromImage(atlasImage);
}
Some constants that are used:
internal const int TEXTURE_ATLAS_SIZE = 8192;
internal const int TILES_PER_ROW = TEXTURE_ATLAS_SIZE / GenerationSettings.PIXELS_PER_TILE;
internal const float TILE_SIZE = (float)GenerationSettings.PIXELS_PER_TILE / TEXTURE_ATLAS_SIZE;
internal const int PIXELS_PER_TILE = 64;
If there is any more information needed let me know and I will provide it promptly!
Thank you for your help in advance mighty hero!