From 1314db72958c864d401e531119e8f1ff392d6404 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 19 Jun 2026 03:24:18 -0400 Subject: [PATCH] WIP texture array sprite batch + gl3 min --- android/AndroidManifest.xml | 2 +- .../sprites/blocks/environment/env-error.png | Bin 287 -> 0 bytes .../sprites/blocks/environment/pack.json | 9 --- core/assets-raw/sprites/pack.json | 2 +- core/assets-raw/sprites/rubble/pack.json | 9 --- core/assets-raw/sprites/ui/pack.json | 9 --- core/src/mindustry/ClientLauncher.java | 15 +--- .../mindustry/editor/EditorSpriteCache.java | 2 +- core/src/mindustry/graphics/CubemapMesh.java | 4 +- .../src/mindustry/graphics/FloorRenderer.java | 71 +++++++++++------- .../src/mindustry/graphics/IntelGpuCheck.java | 44 ----------- .../mindustry/graphics/ParticleRenderer.java | 2 +- .../mindustry/graphics/g3d/MeshBuilder.java | 22 +++--- core/src/mindustry/ui/Fonts.java | 36 ++------- .../mindustry/ui/dialogs/EffectsDialog.java | 2 +- .../mindustry/desktop/DesktopLauncher.java | 12 +-- gradle.properties | 2 +- tools/build.gradle | 12 --- 18 files changed, 75 insertions(+), 180 deletions(-) delete mode 100644 core/assets-raw/sprites/blocks/environment/env-error.png delete mode 100644 core/assets-raw/sprites/blocks/environment/pack.json delete mode 100644 core/assets-raw/sprites/rubble/pack.json delete mode 100644 core/assets-raw/sprites/ui/pack.json delete mode 100644 core/src/mindustry/graphics/IntelGpuCheck.java diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 868acaa1aa..40a60c9def 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,7 +1,7 @@ - + diff --git a/core/assets-raw/sprites/blocks/environment/env-error.png b/core/assets-raw/sprites/blocks/environment/env-error.png deleted file mode 100644 index b72971ab8a2b0ae2df236e66a24e586d1436ecf7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287 zcmV+)0pR|LP)Px#*-1n}R9J=WmfH@*AP7WZ|No!aCmTYTfoN+tS$U~e3&#sn)XYp?w9lKt4*&&F z)%3Xy09gd_ebz<`m^uQ#D`o}*`#H!cKo&qmsKabNGYT*Qp@1V;9QXYSNOuVlI*Q*- z!#j;##4P~rESM3SRe`zyGR3RfOf8Xu#{LBmQ!Z-2X#4Z5(lmpKY1tB@Rr5ZgPYB?5 z!hgtwCEF$DQ)HtMA^Q&@ng)2P2x$Sti^Tr(maxTextureSize >= 4096 ? "sprites/sprites.aatls" : "sprites/fallback/sprites.aatls", TextureAtlas.class)).loaded = t -> atlas = t; + assets.load(new AssetDescriptor<>("sprites/sprites.aatls", TextureAtlas.class)).loaded = t -> { + atlas = t; + Fonts.mergeFontAtlas(atlas); + }; assets.loadRun("maps", Map.class, () -> maps.loadPreviews()); Musics.load(); @@ -176,7 +170,6 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform }); assets.load(mods); - assets.loadRun("mergeUI", PixmapPacker.class, () -> {}, () -> Fonts.mergeFontAtlas(atlas)); add(logic = new Logic()); add(control = new Control()); diff --git a/core/src/mindustry/editor/EditorSpriteCache.java b/core/src/mindustry/editor/EditorSpriteCache.java index f659b6b84f..f7f7478611 100644 --- a/core/src/mindustry/editor/EditorSpriteCache.java +++ b/core/src/mindustry/editor/EditorSpriteCache.java @@ -42,7 +42,7 @@ public class EditorSpriteCache implements Disposable{ * @param indices The shared index data in standard quad format, as seen in SpriteBatch. * Since this data is static, it should be the same across all caches, and be large enough to accommodate all sprites. * */ - public void build(IndexData indices){ + public void build(IndexBufferObject indices){ if(mesh != null) mesh.dispose(); mesh = new Mesh(true, index / vertexSize, 0, diff --git a/core/src/mindustry/graphics/CubemapMesh.java b/core/src/mindustry/graphics/CubemapMesh.java index 67ef264d86..cc59939292 100644 --- a/core/src/mindustry/graphics/CubemapMesh.java +++ b/core/src/mindustry/graphics/CubemapMesh.java @@ -60,8 +60,8 @@ public class CubemapMesh implements Disposable{ this.map = map; this.map.setFilter(TextureFilter.linear); this.mesh = new Mesh(true, vertices.length, 0, VertexAttribute.position3); - mesh.getVerticesBuffer().limit(vertices.length); - mesh.getVerticesBuffer().put(vertices, 0, vertices.length); + mesh.getVertices().limit(vertices.length); + mesh.getVertices().put(vertices, 0, vertices.length); shader = new Shader(Core.files.internal("shaders/cubemap.vert"), Core.files.internal("shaders/cubemap.frag")); } diff --git a/core/src/mindustry/graphics/FloorRenderer.java b/core/src/mindustry/graphics/FloorRenderer.java index 7a4bc49428..6f9793a4fa 100644 --- a/core/src/mindustry/graphics/FloorRenderer.java +++ b/core/src/mindustry/graphics/FloorRenderer.java @@ -32,11 +32,11 @@ import static mindustry.Vars.*; public class FloorRenderer{ public static boolean growSprites = true; - private static final VertexAttribute[] attributes = {VertexAttribute.packedPosition, VertexAttribute.color, VertexAttribute.packedTexCoords}; + private static final VertexAttribute[] attributes = {VertexAttribute.packedPosition, VertexAttribute.color, VertexAttribute.packedTexCoords, VertexAttribute.depthCoords}; private static final int chunksize = 30, //todo 32? chunkunits = chunksize * tilesize, - vertexSize = 1 + 1 + 1, + vertexSize = 1 + 1 + 1 + 1, spriteSize = vertexSize * 4, maxSprites = chunksize * chunksize * 9; private static final float packPad = tilesize * 8f; @@ -73,25 +73,29 @@ public class FloorRenderer{ attribute vec4 a_position; attribute vec4 a_color; attribute vec2 a_texCoord0; + attribute float a_depth; uniform mat4 u_projectionViewMatrix; varying vec4 v_color; varying vec2 v_texCoords; + varying float v_depth; void main(){ v_color = a_color; v_color.a = v_color.a * (255.0/254.0); v_texCoords = a_texCoord0; + v_depth = a_depth; gl_Position = u_projectionViewMatrix * a_position; } """, """ varying vec4 v_color; varying vec2 v_texCoords; - uniform sampler2D u_texture; + varying float v_depth; + uniform sampler2DArray u_texture; void main(){ - gl_FragColor = v_color * texture2D(u_texture, v_texCoords); + gl_FragColor = v_color * texture(u_texture, vec3(v_texCoords, v_depth)); } """); @@ -456,24 +460,29 @@ public class FloorRenderer{ float v = region.v2; float u2 = region.u2; float v2 = region.v; + float depth = region.getDepth(); float color = this.colorPacked; - verts[idx] = pack(x1, y1); - verts[idx + 1] = color; - verts[idx + 2] = Pack.packUv(u, v); + verts[idx] = pack(x1, y1); + verts[idx + 1] = color; + verts[idx + 2] = Pack.packUv(u, v); + verts[idx + 3] = depth; - verts[idx + 3] = pack(x2, y2); - verts[idx + 4] = color; - verts[idx + 5] = Pack.packUv(u, v2); + verts[idx + 4] = pack(x2, y2); + verts[idx + 5] = color; + verts[idx + 6] = Pack.packUv(u, v2); + verts[idx + 7] = depth; - verts[idx + 6] = pack(x3, y3); - verts[idx + 7] = color; - verts[idx + 8] = Pack.packUv(u2, v2); + verts[idx + 8] = pack(x3, y3); + verts[idx + 9] = color; + verts[idx + 10] = Pack.packUv(u2, v2); + verts[idx + 11] = depth; - verts[idx + 9] = pack(x4, y4); - verts[idx + 10] = color; - verts[idx + 11] = Pack.packUv(u2, v); + verts[idx + 12] = pack(x4, y4); + verts[idx + 13] = color; + verts[idx + 14] = Pack.packUv(u2, v); + verts[idx + 15] = depth; }else{ float fx2 = x + width; float fy2 = y + height; @@ -481,24 +490,29 @@ public class FloorRenderer{ float v = region.v2; float u2 = region.u2; float v2 = region.v; + float depth = region.getDepth(); float color = this.colorPacked; - verts[idx] = pack(x, y); - verts[idx + 1] = color; - verts[idx + 2] = Pack.packUv(u, v); + verts[idx] = pack(x, y); + verts[idx + 1] = color; + verts[idx + 2] = Pack.packUv(u, v); + verts[idx + 3] = depth; - verts[idx + 3] = pack(x, fy2); - verts[idx + 4] = color; - verts[idx + 5] = Pack.packUv(u, v2); + verts[idx + 4] = pack(x, fy2); + verts[idx + 5] = color; + verts[idx + 6] = Pack.packUv(u, v2); + verts[idx + 7] = depth; - verts[idx + 6] = pack(fx2, fy2); - verts[idx + 7] = color; - verts[idx + 8] = Pack.packUv(u2, v2); + verts[idx + 8] = pack(fx2, fy2); + verts[idx + 9] = color; + verts[idx + 10] = Pack.packUv(u2, v2); + verts[idx + 11] = depth; - verts[idx + 9] = pack(fx2, y); - verts[idx + 10] = color; - verts[idx + 11] = Pack.packUv(u2, v); + verts[idx + 12] = pack(fx2, y); + verts[idx + 13] = color; + verts[idx + 14] = Pack.packUv(u2, v); + verts[idx + 15] = depth; } } @@ -519,6 +533,7 @@ public class FloorRenderer{ @Override protected void draw(Texture texture, float[] spriteVertices, int offset, int count){ + //TODO broken if(spriteVertices.length != 20){ throw new IllegalArgumentException("cached vertices must be in non-mixcolor format (20 per sprite, 5 per vertex)"); } diff --git a/core/src/mindustry/graphics/IntelGpuCheck.java b/core/src/mindustry/graphics/IntelGpuCheck.java deleted file mode 100644 index 719b58a566..0000000000 --- a/core/src/mindustry/graphics/IntelGpuCheck.java +++ /dev/null @@ -1,44 +0,0 @@ -package mindustry.graphics; - -import arc.files.*; -import arc.util.*; - -import java.util.*; - -public class IntelGpuCheck{ - private static boolean wasIntel, checkedLastLaunch; - - /** initialize intel version check for the next application launch */ - public static void init(String vendor){ - if(!OS.isWindows) return; - - boolean isIntel = vendor.toLowerCase(Locale.ROOT).contains("intel"); - try{ - Fi file = new Fi(OS.getAppDataDirectoryString("Mindustry")).child("was_intel_gpu"); - if(isIntel){ - file.writeString("1"); - }else if(file.exists()){ - file.delete(); - } - }catch(Throwable e){ - Log.err(e); - } - } - - /** @return whether the last launch used an intel GPU on Windows */ - public static boolean wasIntel(){ - if(!OS.isWindows) return false; - if(checkedLastLaunch) return wasIntel; - checkedLastLaunch = true; - - try{ - Fi file = new Fi(OS.getAppDataDirectoryString("Mindustry")).child("was_intel_gpu"); - if(file.exists() && file.readString().equals("1")){ - return wasIntel = true; - } - }catch(Throwable e){ - Log.err("Failed to check whether the last launch used an intel GPU.", e); - } - return wasIntel = false; - } -} diff --git a/core/src/mindustry/graphics/ParticleRenderer.java b/core/src/mindustry/graphics/ParticleRenderer.java index 32aeec37d5..d79933d7aa 100644 --- a/core/src/mindustry/graphics/ParticleRenderer.java +++ b/core/src/mindustry/graphics/ParticleRenderer.java @@ -163,7 +163,7 @@ public class ParticleRenderer{ } void uploadMeshData(Mesh mesh){ - var buffer = mesh.getVerticesBuffer(); + var buffer = mesh.getVertices(); buffer.position(0); buffer.limit(vertexBufferLength); diff --git a/core/src/mindustry/graphics/g3d/MeshBuilder.java b/core/src/mindustry/graphics/g3d/MeshBuilder.java index 6fcdec0925..4cb4f1dd0b 100644 --- a/core/src/mindustry/graphics/g3d/MeshBuilder.java +++ b/core/src/mindustry/graphics/g3d/MeshBuilder.java @@ -24,14 +24,14 @@ public class MeshBuilder{ items[i] *= radius; } - mesh.getVerticesBuffer().put(items, 0, result.vertices.size); + mesh.getVertices().put(items, 0, result.vertices.size); short[] indices = new short[result.indices.size]; for(int i = 0; i < result.indices.size; i++){ indices[i] = (short)result.indices.items[i]; } - mesh.getIndicesBuffer().put(indices); + mesh.getIndices().put(indices); return end(mesh); } @@ -59,7 +59,7 @@ public class MeshBuilder{ floats[6] = v2.z * scale; floats[7] = col; - mesh.getVerticesBuffer().put(floats); + mesh.getVertices().put(floats); } } @@ -175,7 +175,7 @@ public class MeshBuilder{ shorts[11] = (short)(position + 5); } - mesh.getIndicesBuffer().put(shorts, 0, c.length > 5 ? 12 : 9); + mesh.getIndices().put(shorts, 0, c.length > 5 ? 12 : 9); position += c.length; }else{ @@ -216,21 +216,21 @@ public class MeshBuilder{ Mesh mesh = new Mesh(true, vertices, indices, attributes.toArray(VertexAttribute.class)); - mesh.getVerticesBuffer().limit(mesh.getVerticesBuffer().capacity()); - mesh.getVerticesBuffer().position(0); + mesh.getVertices().limit(mesh.getVertices().capacity()); + mesh.getVertices().position(0); if(indices > 0){ - mesh.getIndicesBuffer().limit(mesh.getIndicesBuffer().capacity()); - mesh.getIndicesBuffer().position(0); + mesh.getIndices().limit(mesh.getIndices().capacity()); + mesh.getIndices().position(0); } return mesh; } private static Mesh end(Mesh mesh){ - mesh.getVerticesBuffer().limit(mesh.getVerticesBuffer().position()); + mesh.getVertices().limit(mesh.getVertices().position()); if(mesh.getNumIndices() > 0){ - mesh.getIndicesBuffer().limit(mesh.getIndicesBuffer().position()); + mesh.getIndices().limit(mesh.getIndices().position()); } return mesh; @@ -282,7 +282,7 @@ public class MeshBuilder{ if(floats.length > 7) floats[7] = emissive; } - mesh.getVerticesBuffer().put(floats); + mesh.getVertices().put(floats); } private static float packNormals(float x, float y, float z){ diff --git a/core/src/mindustry/ui/Fonts.java b/core/src/mindustry/ui/Fonts.java index d71e88ff86..3fc4a8fdf3 100644 --- a/core/src/mindustry/ui/Fonts.java +++ b/core/src/mindustry/ui/Fonts.java @@ -12,7 +12,6 @@ import arc.graphics.Texture.*; import arc.graphics.g2d.*; import arc.graphics.g2d.Font.*; import arc.graphics.g2d.PixmapPacker.*; -import arc.graphics.g2d.TextureAtlas.*; import arc.math.geom.*; import arc.scene.style.*; import arc.scene.ui.layout.*; @@ -236,9 +235,9 @@ public class Fonts{ /** Called from a static context for use in the loading screen.*/ public static void loadDefaultFont(){ - int max = Gl.getInt(Gl.maxTextureSize); + //TOOD: which size to use? + UI.packer = new PixmapPacker(4096, 2048, 2, true); - UI.packer = new PixmapPacker(max >= 4096 ? 4096 : 2048, 2048, 2, true); Core.assets.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(Core.files::internal)); Core.assets.setLoader(Font.class, null, new FreetypeFontLoader(Core.files::internal){ ObjectSet scaled = new ObjectSet<>(); @@ -279,37 +278,14 @@ public class Fonts{ } /** Merges the UI and font atlas together for better performance. */ + //TODO: does nothing at the moment. public static void mergeFontAtlas(TextureAtlas atlas){ - //grab all textures from the ui page, remove all the regions assigned to it, then copy them over to UI.packer and replace the texture in this atlas. - - //grab old UI texture and regions... - Texture texture = atlas.find("logo").texture; + if(true) return; + Texture texture = atlas.find("ui-page-placeholder").texture; Page page = UI.packer.getPages().first(); - - Seq regions = atlas.getRegions().select(t -> t.texture == texture); - for(AtlasRegion region : regions){ - //get new pack rect - page.setDirty(false); - Rect rect = UI.packer.pack(region.name, atlas.getPixmap(region), region.splits, region.pads); - - //set new texture - region.texture = UI.packer.getPages().first().getTexture(); - //set its new position - region.set((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height); - //add old texture - atlas.getTextures().add(region.texture); - //clear it - region.pixmapRegion = null; - } - - //remove old texture, it will no longer be used - atlas.getTextures().remove(texture); - texture.dispose(); - atlas.disposePixmap(texture); - page.setDirty(true); - page.updateTexture(TextureFilter.linear, TextureFilter.linear, false); + page.texture = texture; } public static TextureRegionDrawable getGlyph(Font font, char glyph){ diff --git a/core/src/mindustry/ui/dialogs/EffectsDialog.java b/core/src/mindustry/ui/dialogs/EffectsDialog.java index 98db4ea91a..4fc37766b9 100644 --- a/core/src/mindustry/ui/dialogs/EffectsDialog.java +++ b/core/src/mindustry/ui/dialogs/EffectsDialog.java @@ -142,7 +142,7 @@ public class EffectsDialog extends BaseDialog{ @Override protected void draw(Texture texture, float[] spriteVertices, int offset, int count){ - for(int i = offset; i < count; i += SpriteBatch.VERTEX_SIZE){ + for(int i = offset; i < count; i += SpriteBatch.vertexSize){ max(spriteVertices[i], spriteVertices[i + 1]); } } diff --git a/desktop/src/mindustry/desktop/DesktopLauncher.java b/desktop/src/mindustry/desktop/DesktopLauncher.java index 6b23a4353c..0ee801cd88 100644 --- a/desktop/src/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/mindustry/desktop/DesktopLauncher.java @@ -20,7 +20,6 @@ import mindustry.core.*; import mindustry.desktop.steam.*; import mindustry.game.EventType.*; import mindustry.gen.*; -import mindustry.graphics.*; import mindustry.mod.Mods.*; import mindustry.net.*; import mindustry.net.Net.*; @@ -57,17 +56,12 @@ public class DesktopLauncher extends ClientLauncher{ width = 900; height = 700; - //on Windows, Intel drivers might be buggy with OpenGL 3.x, so only use 2.x. See https://github.com/Anuken/Mindustry/issues/11041 - if(IntelGpuCheck.wasIntel()){ - allowGl30 = false; - coreProfile = false; - glVersions = new int[][]{{2, 1}, {2, 0}}; - }else if(OS.isMac){ + if(OS.isMac){ //MacOS supports 4.1 at most - glVersions = new int[][]{{4, 1}, {3, 2}, {2, 1}, {2, 0}}; + glVersions = new int[][]{{4, 1}, {3, 2}}; }else{ //try essentially every OpenGL version - glVersions = new int[][]{{4, 6}, {4, 5}, {4, 4}, {4, 1}, {3, 3}, {3, 2}, {3, 1}, {2, 1}, {2, 0}}; + glVersions = new int[][]{{4, 6}, {4, 5}, {4, 4}, {4, 1}, {3, 3}, {3, 2}, {3, 1}, {3, 0}}; } for(int i = 0; i < arg.length; i++){ diff --git a/gradle.properties b/gradle.properties index 3cf7883b6c..ece5b8aae5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,4 +26,4 @@ org.gradle.caching=true org.gradle.internal.http.socketTimeout=100000 org.gradle.internal.http.connectionTimeout=100000 android.enableR8.fullMode=false -archash=abb6cc1a11 +archash=f4336eefed diff --git a/tools/build.gradle b/tools/build.gradle index c2b15be338..4d9aa030af 100644 --- a/tools/build.gradle +++ b/tools/build.gradle @@ -175,18 +175,6 @@ tasks.register('pack'){ //pack normal sprites TexturePacker.process(new File(rootDir, "core/assets-raw/sprites_out/").absolutePath, new File(rootDir, "core/assets/sprites/").absolutePath, "sprites.aatls") - - println("\n\nPacking fallback 2048 sprites...\n\n") - - //replace config file contents - fileTree(dir: '../core/assets-raw/sprites_out/', include: "**/*.json").visit{ file -> - if(!file.isDirectory()) file.file.text = file.file.text.replace("4096", "2048") - } - - //pack fallback 2048x2048 sprites - disabled when debugging - if(!project.hasProperty("args")){ - TexturePacker.process(new File(rootDir, "core/assets-raw/sprites_out/").absolutePath, new File(rootDir, "core/assets/sprites/fallback/").absolutePath, "sprites.aatls") - } } }