diff --git a/android/assets/jsons/translations/template.properties b/android/assets/jsons/translations/template.properties index 2bc69260df..abbb3ac933 100644 --- a/android/assets/jsons/translations/template.properties +++ b/android/assets/jsons/translations/template.properties @@ -737,7 +737,6 @@ Unit icon opacity = ### Performance subgroup Continuous rendering = -Experimental rendering improvements = When disabled, saves battery life but certain animations will be suspended = ## Gameplay tab diff --git a/core/src/com/unciv/models/metadata/GameSettings.kt b/core/src/com/unciv/models/metadata/GameSettings.kt index 2446610ceb..ee78f8abe1 100644 --- a/core/src/com/unciv/models/metadata/GameSettings.kt +++ b/core/src/com/unciv/models/metadata/GameSettings.kt @@ -78,7 +78,6 @@ class GameSettings { val showPixelUnits: Boolean get() = unitSet != null var showPixelImprovements: Boolean = true var continuousRendering = false - var experimentalRendering = false var orderTradeOffersByAmount = true var confirmNextTurn = false var windowState = WindowState() diff --git a/core/src/com/unciv/ui/popups/options/DisplayTab.kt b/core/src/com/unciv/ui/popups/options/DisplayTab.kt index f7969330ea..227d66b478 100644 --- a/core/src/com/unciv/ui/popups/options/DisplayTab.kt +++ b/core/src/com/unciv/ui/popups/options/DisplayTab.kt @@ -99,12 +99,6 @@ fun displayTab( ) continuousRenderingLabel.wrap = true add(continuousRenderingLabel).colspan(2).padTop(10f).row() - - optionsPopup.addCheckbox(this, "Experimental rendering improvements", settings.experimentalRendering) { - settings.experimentalRendering = it - onChange() - } - } private fun addMinimapSizeSlider(table: Table, settings: GameSettings, selectBoxMinWidth: Float) { diff --git a/core/src/com/unciv/ui/screens/basescreen/TextureArraySpriteBatch.java b/core/src/com/unciv/ui/screens/basescreen/TextureArraySpriteBatch.java deleted file mode 100644 index ae164323cd..0000000000 --- a/core/src/com/unciv/ui/screens/basescreen/TextureArraySpriteBatch.java +++ /dev/null @@ -1,1451 +0,0 @@ -package com.unciv.ui.screens.basescreen; - -import java.nio.Buffer; -import java.nio.IntBuffer; -import java.util.Arrays; - -import com.badlogic.gdx.Application.ApplicationType; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.GL20; -import com.badlogic.gdx.graphics.Mesh; -import com.badlogic.gdx.graphics.Mesh.VertexDataType; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.VertexAttribute; -import com.badlogic.gdx.graphics.VertexAttributes.Usage; -import com.badlogic.gdx.graphics.g2d.Batch; -import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.glutils.ShaderProgram; -import com.badlogic.gdx.math.Affine2; -import com.badlogic.gdx.math.MathUtils; -import com.badlogic.gdx.math.Matrix4; -import com.badlogic.gdx.utils.BufferUtils; - -/** Draws batched quads using indices. - *
- * This is an optimized version of the SpriteBatch that maintains an LFU texture-cache to combine draw calls with different - * textures effectively. - *
- * Use this Batch if you frequently utilize more than a single texture between calling {@link#begin()} and {@link#end()}. An - * example would be if your Atlas is spread over multiple Textures or if you draw with individual Textures. - * - * @see Batch - * @see SpriteBatch - * - * @author mzechner (Original SpriteBatch) - * @author Nathan Sweet (Original SpriteBatch) - * @author VaTTeRGeR (TextureArray Extension) */ - -public class TextureArraySpriteBatch implements Batch { - - private int idx = 0; - - private final Mesh mesh; - - private final float[] vertices; - - /** 2 coords, 1 color, 2 UV */ - private final int unmodifiedVertexSize = 5; - /** 4 vertices for each sprite (rectangle) */ - private final int unmodifiedSpriteSize = 4 * unmodifiedVertexSize; - - /** 2 coords, 1 color, 2 UV, 1 texture id */ - private final int spriteVertexSize = 6; - /** 4 vertices for each sprite (rectangle) */ - private final int spriteSize = spriteVertexSize * 4; - - /** The maximum number of available texture units for the fragment shader */ - private static int maxTextureUnits = -1; - - /** Textures in use (index: Texture Unit, value: Texture) */ - private final Texture[] usedTextures; - - /** LFU Array (index: Texture Unit Index - value: Access frequency) */ - private final int[] usedTexturesLFU; - - /** Gets sent to the fragment shader as an uniform "uniform sampler2d[X] u_textures" */ - private final IntBuffer textureUnitIndicesBuffer; - - private float invTexWidth = 0, invTexHeight = 0; - - private boolean drawing = false; - - private final Matrix4 transformMatrix = new Matrix4(); - private final Matrix4 projectionMatrix = new Matrix4(); - private final Matrix4 combinedMatrix = new Matrix4(); - - private boolean blendingDisabled = false; - private int blendSrcFunc = GL20.GL_SRC_ALPHA; - private int blendDstFunc = GL20.GL_ONE_MINUS_SRC_ALPHA; - private int blendSrcFuncAlpha = GL20.GL_SRC_ALPHA; - private int blendDstFuncAlpha = GL20.GL_ONE_MINUS_SRC_ALPHA; - - private ShaderProgram shader = null; - private ShaderProgram customShader = null; - - private static String shaderErrorLog = null; - - private boolean ownsShader; - - private final Color color = new Color(1, 1, 1, 1); - private float colorPacked = Color.WHITE_FLOAT_BITS; - - /** Number of render calls since the last {@link #begin()}. **/ - public int renderCalls = 0; - - /** Number of rendering calls, ever. Will not be reset unless set manually. **/ - public int totalRenderCalls = 0; - - /** The maximum number of sprites rendered in one batch so far. **/ - public int maxSpritesInBatch = 0; - - /** The current number of textures in the LFU cache. Gets reset when calling {@link#begin()} **/ - private int currentTextureLFUSize = 0; - - /** The current number of texture swaps in the LFU cache. Gets reset when calling {@link#begin()} **/ - private int currentTextureLFUSwaps = 0; - - /** Constructs a new TextureArraySpriteBatch with a size of 1000, one buffer, and the default shader. - * @see TextureArraySpriteBatch#TextureArraySpriteBatch(int, ShaderProgram) */ - public TextureArraySpriteBatch () { - this(1000); - } - - /** Constructs a TextureArraySpriteBatch with one buffer and the default shader. - * @see TextureArraySpriteBatch#TextureArraySpriteBatch(int, ShaderProgram) */ - public TextureArraySpriteBatch (int size) { - this(size, null); - } - - /** Constructs a new TextureArraySpriteBatch. Sets the projection matrix to an orthographic projection with y-axis point - * upwards, x-axis point to the right and the origin being in the bottom left corner of the screen. The projection will be - * pixel perfect with respect to the current screen resolution. - *
- * The defaultShader specifies the shader to use. Note that the names for uniforms for this default shader are different than
- * the ones expect for shaders set with {@link #setShader(ShaderProgram)}.
- * @param size The max number of sprites in a single batch. Max of 8191.
- * @param defaultShader The default shader to use. This is not owned by the TextureArraySpriteBatch and must be disposed
- * separately.
- * @throws IllegalStateException Thrown if the device does not support texture arrays. Make sure to implement a Fallback to
- * {@link SpriteBatch} in case Texture Arrays are not supported on a clients device.
- * @See {@link#createDefaultShader()} {@link#getMaxTextureUnits()} */
- public TextureArraySpriteBatch (int size, ShaderProgram defaultShader) throws IllegalStateException {
-
- // 32767 is max vertex index, so 32767 / 4 vertices per sprite = 8191 sprites max.
- if (size > 8191) throw new IllegalArgumentException("Can't have more than 8191 sprites per batch: " + size);
-
- getMaxTextureUnits();
-
- if (maxTextureUnits == 0) {
- throw new IllegalStateException(
- "Texture Arrays are not supported on this device:" + System.lineSeparator() + shaderErrorLog);
- }
-
- if (defaultShader == null) {
- shader = createDefaultShader(maxTextureUnits);
- ownsShader = true;
-
- } else {
- shader = defaultShader;
- ownsShader = false;
- }
-
- usedTextures = new Texture[maxTextureUnits];
- usedTexturesLFU = new int[maxTextureUnits];
-
- // This contains the numbers 0 ... maxTextureUnits - 1. We send these to the shader as an uniform.
- textureUnitIndicesBuffer = BufferUtils.newIntBuffer(maxTextureUnits);
- for (int i = 0; i < maxTextureUnits; i++) {
- textureUnitIndicesBuffer.put(i);
- }
- ((Buffer) textureUnitIndicesBuffer).flip();
-
- VertexDataType vertexDataType = (Gdx.gl30 != null) ? VertexDataType.VertexBufferObjectWithVAO : VertexDataType.VertexArray;
-
- // The vertex data is extended with one float for the texture index.
- mesh = new Mesh(vertexDataType, false, size * 4, size * 6,
- new VertexAttribute(Usage.Position, 2, ShaderProgram.POSITION_ATTRIBUTE),
- new VertexAttribute(Usage.ColorPacked, 4, ShaderProgram.COLOR_ATTRIBUTE),
- new VertexAttribute(Usage.TextureCoordinates, 2, ShaderProgram.TEXCOORD_ATTRIBUTE + "0"),
- new VertexAttribute(Usage.Generic, 1, "texture_index"));
-
- projectionMatrix.setToOrtho2D(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
-
- vertices = new float[size * spriteSize];
-
- int len = size * 6;
- short[] indices = new short[len];
- short j = 0;
- for (int i = 0; i < len; i += 6, j += 4) {
- indices[i] = j;
- indices[i + 1] = (short)(j + 1);
- indices[i + 2] = (short)(j + 2);
- indices[i + 3] = (short)(j + 2);
- indices[i + 4] = (short)(j + 3);
- indices[i + 5] = j;
- }
-
- mesh.setIndices(indices);
- }
-
- /** Returns a new instance of the default shader used by TextureArraySpriteBatch for GL2 when no shader is specified.
- * @See {@link#getMaxTextureUnits()} */
- public static ShaderProgram createDefaultShader (int maxTextureUnits) {
-
- // The texture index is just passed to the fragment shader, maybe there's an more elegant way.
- String vertexShader = "attribute vec4 " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" //
- + "attribute vec4 " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" //
- + "attribute vec2 " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" //
- + "attribute float texture_index;\n" //
- + "uniform mat4 u_projTrans;\n" //
- + "varying vec4 v_color;\n" //
- + "varying vec2 v_texCoords;\n" //
- + "varying float v_texture_index;\n" //
- + "\n" //
- + "void main()\n" //
- + "{\n" //
- + " v_color = " + ShaderProgram.COLOR_ATTRIBUTE + ";\n" //
- + " v_color.a = v_color.a * (255.0/254.0);\n" //
- + " v_texCoords = " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" //
- + " v_texture_index = texture_index;\n" //
- + " gl_Position = u_projTrans * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" //
- + "}\n";
-
- // The texture is simply selected from an array of textures
- String fragmentShader = "#ifdef GL_ES\n" //
- + "#define LOWP lowp\n" //
- + "precision mediump float;\n" //
- + "#else\n" //
- + "#define LOWP\n" //
- + "#endif\n" //
- + "varying LOWP vec4 v_color;\n" //
- + "varying vec2 v_texCoords;\n" //
- + "varying float v_texture_index;\n" //
- + "uniform sampler2D u_textures[" + maxTextureUnits + "];\n" //
- + "void main()\n"//
- + "{\n" //
- + " int index = int(v_texture_index);" //
- + " gl_FragColor = v_color * texture2D(u_textures[index], v_texCoords);\n" //
- + "}";
-
- final ApplicationType appType = Gdx.app.getType();
-
- if (appType == ApplicationType.Android || appType == ApplicationType.iOS || appType == ApplicationType.WebGL) {
- fragmentShader = "#version 100\n" + fragmentShader;
- } else {
- fragmentShader = "#version 150\n" + fragmentShader;
- }
-
- ShaderProgram shader = new ShaderProgram(vertexShader, fragmentShader);
-
- if (!shader.isCompiled()) {
- throw new IllegalArgumentException("Error compiling shader: " + shader.getLog());
- }
-
- return shader;
- }
-
- @Override
- public void begin () {
-
- if (drawing) throw new IllegalStateException("TextureArraySpriteBatch.end must be called before begin.");
-
- renderCalls = 0;
-
- currentTextureLFUSize = 0;
- currentTextureLFUSwaps = 0;
-
- Arrays.fill(usedTextures, null);
- Arrays.fill(usedTexturesLFU, 0);
-
- Gdx.gl.glDepthMask(false);
-
- if (customShader != null) {
- customShader.begin();
- } else {
- shader.begin();
- }
-
- setupMatrices();
-
- drawing = true;
- }
-
- @Override
- public void end () {
-
- if (!drawing) throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before end.");
-
- if (idx > 0) flush();
-
- drawing = false;
-
- GL20 gl = Gdx.gl;
-
- gl.glDepthMask(true);
-
- if (isBlendingEnabled()) {
- gl.glDisable(GL20.GL_BLEND);
- }
-
- if (customShader != null) {
- customShader.end();
- } else {
- shader.end();
- }
- }
-
- @Override
- public void dispose () {
-
- mesh.dispose();
-
- if (ownsShader && shader != null) {
- shader.dispose();
- }
- }
-
- @Override
- public void setColor (Color tint) {
- color.set(tint);
- colorPacked = tint.toFloatBits();
- }
-
- @Override
- public void setColor (float r, float g, float b, float a) {
- color.set(r, g, b, a);
- colorPacked = color.toFloatBits();
- }
-
- @Override
- public Color getColor () {
- return color;
- }
-
- @Override
- public void setPackedColor (float packedColor) {
- Color.abgr8888ToColor(color, packedColor);
- this.colorPacked = packedColor;
- }
-
- @Override
- public float getPackedColor () {
- return colorPacked;
- }
-
- @Override
- public void draw (Texture texture, float x, float y, float originX, float originY, float width, float height, float scaleX,
- float scaleY, float rotation, int srcX, int srcY, int srcWidth, int srcHeight, boolean flipX, boolean flipY) {
- if (!drawing) throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before draw.");
-
- float[] vertices = this.vertices;
-
- flushIfFull();
-
- final float ti = activateTexture(texture);
-
- // bottom left and top right corner points relative to origin
- final float worldOriginX = x + originX;
- final float worldOriginY = y + originY;
- float fx = -originX;
- float fy = -originY;
- float fx2 = width - originX;
- float fy2 = height - originY;
-
- // scale
- if (scaleX != 1 || scaleY != 1) {
- fx *= scaleX;
- fy *= scaleY;
- fx2 *= scaleX;
- fy2 *= scaleY;
- }
-
- // construct corner points, start from top left and go counter clockwise
- final float p1x = fx;
- final float p1y = fy;
- final float p2x = fx;
- final float p2y = fy2;
- final float p3x = fx2;
- final float p3y = fy2;
- final float p4x = fx2;
- final float p4y = fy;
-
- float x1;
- float y1;
- float x2;
- float y2;
- float x3;
- float y3;
- float x4;
- float y4;
-
- // rotate
- if (rotation != 0) {
- final float cos = MathUtils.cosDeg(rotation);
- final float sin = MathUtils.sinDeg(rotation);
-
- x1 = cos * p1x - sin * p1y;
- y1 = sin * p1x + cos * p1y;
-
- x2 = cos * p2x - sin * p2y;
- y2 = sin * p2x + cos * p2y;
-
- x3 = cos * p3x - sin * p3y;
- y3 = sin * p3x + cos * p3y;
-
- x4 = x1 + (x3 - x2);
- y4 = y3 - (y2 - y1);
- } else {
- x1 = p1x;
- y1 = p1y;
-
- x2 = p2x;
- y2 = p2y;
-
- x3 = p3x;
- y3 = p3y;
-
- x4 = p4x;
- y4 = p4y;
- }
-
- x1 += worldOriginX;
- y1 += worldOriginY;
- x2 += worldOriginX;
- y2 += worldOriginY;
- x3 += worldOriginX;
- y3 += worldOriginY;
- x4 += worldOriginX;
- y4 += worldOriginY;
-
- float u = srcX * invTexWidth;
- float v = (srcY + srcHeight) * invTexHeight;
- float u2 = (srcX + srcWidth) * invTexWidth;
- float v2 = srcY * invTexHeight;
-
- if (flipX) {
- float tmp = u;
- u = u2;
- u2 = tmp;
- }
-
- if (flipY) {
- float tmp = v;
- v = v2;
- v2 = tmp;
- }
-
- final float color = this.colorPacked;
-
- vertices[idx++] = x1;
- vertices[idx++] = y1;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v;
- vertices[idx++] = ti;
-
- vertices[idx++] = x2;
- vertices[idx++] = y2;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = x3;
- vertices[idx++] = y3;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = x4;
- vertices[idx++] = y4;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v;
- vertices[idx++] = ti;
- }
-
- @Override
- public void draw (Texture texture, float x, float y, float width, float height, int srcX, int srcY, int srcWidth,
- int srcHeight, boolean flipX, boolean flipY) {
-
- if (!drawing) throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before draw.");
-
- float[] vertices = this.vertices;
-
- flushIfFull();
-
- final float ti = activateTexture(texture);
-
- float u = srcX * invTexWidth;
- float v = (srcY + srcHeight) * invTexHeight;
- float u2 = (srcX + srcWidth) * invTexWidth;
- float v2 = srcY * invTexHeight;
- final float fx2 = x + width;
- final float fy2 = y + height;
-
- if (flipX) {
- float tmp = u;
- u = u2;
- u2 = tmp;
- }
-
- if (flipY) {
- float tmp = v;
- v = v2;
- v2 = tmp;
- }
-
- float color = this.colorPacked;
-
- vertices[idx++] = x;
- vertices[idx++] = y;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v;
- vertices[idx++] = ti;
-
- vertices[idx++] = x;
- vertices[idx++] = fy2;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = fx2;
- vertices[idx++] = fy2;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = fx2;
- vertices[idx++] = y;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v;
- vertices[idx++] = ti;
- }
-
- @Override
- public void draw (Texture texture, float x, float y, int srcX, int srcY, int srcWidth, int srcHeight) {
- if (!drawing) throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before draw.");
-
- float[] vertices = this.vertices;
-
- flushIfFull();
-
- final float ti = activateTexture(texture);
-
- final float u = srcX * invTexWidth;
- final float v = (srcY + srcHeight) * invTexHeight;
- final float u2 = (srcX + srcWidth) * invTexWidth;
- final float v2 = srcY * invTexHeight;
- final float fx2 = x + srcWidth;
- final float fy2 = y + srcHeight;
-
- float color = this.colorPacked;
-
- vertices[idx++] = x;
- vertices[idx++] = y;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v;
- vertices[idx++] = ti;
-
- vertices[idx++] = x;
- vertices[idx++] = fy2;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = fx2;
- vertices[idx++] = fy2;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = fx2;
- vertices[idx++] = y;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v;
- vertices[idx++] = ti;
- }
-
- @Override
- public void draw (Texture texture, float x, float y, float width, float height, float u, float v, float u2, float v2) {
-
- if (!drawing) throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before draw.");
-
- float[] vertices = this.vertices;
-
- flushIfFull();
-
- final float ti = activateTexture(texture);
-
- final float fx2 = x + width;
- final float fy2 = y + height;
-
- float color = this.colorPacked;
-
- vertices[idx++] = x;
- vertices[idx++] = y;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v;
- vertices[idx++] = ti;
-
- vertices[idx++] = x;
- vertices[idx++] = fy2;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = fx2;
- vertices[idx++] = fy2;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = fx2;
- vertices[idx++] = y;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v;
- vertices[idx++] = ti;
- }
-
- @Override
- public void draw (Texture texture, float x, float y) {
- draw(texture, x, y, texture.getWidth(), texture.getHeight());
- }
-
- @Override
- public void draw (Texture texture, float x, float y, float width, float height) {
-
- if (!drawing) throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before draw.");
-
- float[] vertices = this.vertices;
-
- flushIfFull();
-
- final float ti = activateTexture(texture);
-
- final float fx2 = x + width;
- final float fy2 = y + height;
- final float u = 0;
- final float v = 1;
- final float u2 = 1;
- final float v2 = 0;
-
- float color = this.colorPacked;
-
- vertices[idx++] = x;
- vertices[idx++] = y;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v;
- vertices[idx++] = ti;
-
- vertices[idx++] = x;
- vertices[idx++] = fy2;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = fx2;
- vertices[idx++] = fy2;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = fx2;
- vertices[idx++] = y;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v;
- vertices[idx++] = ti;
- }
-
- @Override
- public void draw (Texture texture, float[] spriteVertices, int offset, int count) {
-
- if (!drawing) {
- throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before draw.");
- }
-
- // Assigns a texture unit to this texture, flushing if none is available
- final float ti = (float)activateTexture(texture);
-
- // We copy by 1 sprite at a time, because we need to additionally inject texture id
- // to each vertex of a sprite.
- for (int srcPos = offset; srcPos < count; srcPos += unmodifiedSpriteSize) {
-
- // Flush if there is not enough space for 1 full sprite (including texture id)
- flushIfFull();
-
- // Copy 4 vertexes
- for (int i=0; i<4; i++) {
-
- // Copy default vertex info
- System.arraycopy(spriteVertices, srcPos+i*unmodifiedVertexSize, vertices, idx, unmodifiedVertexSize);
- idx += 5;
-
- // Additionally inject texture id
- vertices[idx++] = ti;
- }
- }
- }
-
- @Override
- public void draw (TextureRegion region, float x, float y) {
- draw(region, x, y, region.getRegionWidth(), region.getRegionHeight());
- }
-
- @Override
- public void draw (TextureRegion region, float x, float y, float width, float height) {
-
- if (!drawing) throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before draw.");
-
- float[] vertices = this.vertices;
-
- flushIfFull();
-
- final float ti = activateTexture(region.getTexture());
-
- final float fx2 = x + width;
- final float fy2 = y + height;
- final float u = region.getU();
- final float v = region.getV2();
- final float u2 = region.getU2();
- final float v2 = region.getV();
-
- float color = this.colorPacked;
-
- vertices[idx++] = x;
- vertices[idx++] = y;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v;
- vertices[idx++] = ti;
-
- vertices[idx++] = x;
- vertices[idx++] = fy2;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = fx2;
- vertices[idx++] = fy2;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = fx2;
- vertices[idx++] = y;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v;
- vertices[idx++] = ti;
- }
-
- @Override
- public void draw (TextureRegion region, float x, float y, float originX, float originY, float width, float height,
- float scaleX, float scaleY, float rotation) {
-
- if (!drawing) throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before draw.");
-
- float[] vertices = this.vertices;
-
- flushIfFull();
-
- final float ti = activateTexture(region.getTexture());
-
- // bottom left and top right corner points relative to origin
- final float worldOriginX = x + originX;
- final float worldOriginY = y + originY;
- float fx = -originX;
- float fy = -originY;
- float fx2 = width - originX;
- float fy2 = height - originY;
-
- // scale
- if (scaleX != 1 || scaleY != 1) {
- fx *= scaleX;
- fy *= scaleY;
- fx2 *= scaleX;
- fy2 *= scaleY;
- }
-
- // construct corner points, start from top left and go counter clockwise
- final float p1x = fx;
- final float p1y = fy;
- final float p2x = fx;
- final float p2y = fy2;
- final float p3x = fx2;
- final float p3y = fy2;
- final float p4x = fx2;
- final float p4y = fy;
-
- float x1;
- float y1;
- float x2;
- float y2;
- float x3;
- float y3;
- float x4;
- float y4;
-
- // rotate
- if (rotation != 0) {
- final float cos = MathUtils.cosDeg(rotation);
- final float sin = MathUtils.sinDeg(rotation);
-
- x1 = cos * p1x - sin * p1y;
- y1 = sin * p1x + cos * p1y;
-
- x2 = cos * p2x - sin * p2y;
- y2 = sin * p2x + cos * p2y;
-
- x3 = cos * p3x - sin * p3y;
- y3 = sin * p3x + cos * p3y;
-
- x4 = x1 + (x3 - x2);
- y4 = y3 - (y2 - y1);
- } else {
- x1 = p1x;
- y1 = p1y;
-
- x2 = p2x;
- y2 = p2y;
-
- x3 = p3x;
- y3 = p3y;
-
- x4 = p4x;
- y4 = p4y;
- }
-
- x1 += worldOriginX;
- y1 += worldOriginY;
- x2 += worldOriginX;
- y2 += worldOriginY;
- x3 += worldOriginX;
- y3 += worldOriginY;
- x4 += worldOriginX;
- y4 += worldOriginY;
-
- final float u = region.getU();
- final float v = region.getV2();
- final float u2 = region.getU2();
- final float v2 = region.getV();
-
- float color = this.colorPacked;
-
- vertices[idx++] = x1;
- vertices[idx++] = y1;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v;
- vertices[idx++] = ti;
-
- vertices[idx++] = x2;
- vertices[idx++] = y2;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = x3;
- vertices[idx++] = y3;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = x4;
- vertices[idx++] = y4;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v;
- vertices[idx++] = ti;
- }
-
- @Override
- public void draw (TextureRegion region, float x, float y, float originX, float originY, float width, float height,
- float scaleX, float scaleY, float rotation, boolean clockwise) {
-
- if (!drawing) throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before draw.");
-
- float[] vertices = this.vertices;
-
- flushIfFull();
-
- final float ti = activateTexture(region.getTexture());
-
- // bottom left and top right corner points relative to origin
- final float worldOriginX = x + originX;
- final float worldOriginY = y + originY;
- float fx = -originX;
- float fy = -originY;
- float fx2 = width - originX;
- float fy2 = height - originY;
-
- // scale
- if (scaleX != 1 || scaleY != 1) {
- fx *= scaleX;
- fy *= scaleY;
- fx2 *= scaleX;
- fy2 *= scaleY;
- }
-
- // construct corner points, start from top left and go counter clockwise
- final float p1x = fx;
- final float p1y = fy;
- final float p2x = fx;
- final float p2y = fy2;
- final float p3x = fx2;
- final float p3y = fy2;
- final float p4x = fx2;
- final float p4y = fy;
-
- float x1;
- float y1;
- float x2;
- float y2;
- float x3;
- float y3;
- float x4;
- float y4;
-
- // rotate
- if (rotation != 0) {
- final float cos = MathUtils.cosDeg(rotation);
- final float sin = MathUtils.sinDeg(rotation);
-
- x1 = cos * p1x - sin * p1y;
- y1 = sin * p1x + cos * p1y;
-
- x2 = cos * p2x - sin * p2y;
- y2 = sin * p2x + cos * p2y;
-
- x3 = cos * p3x - sin * p3y;
- y3 = sin * p3x + cos * p3y;
-
- x4 = x1 + (x3 - x2);
- y4 = y3 - (y2 - y1);
- } else {
- x1 = p1x;
- y1 = p1y;
-
- x2 = p2x;
- y2 = p2y;
-
- x3 = p3x;
- y3 = p3y;
-
- x4 = p4x;
- y4 = p4y;
- }
-
- x1 += worldOriginX;
- y1 += worldOriginY;
- x2 += worldOriginX;
- y2 += worldOriginY;
- x3 += worldOriginX;
- y3 += worldOriginY;
- x4 += worldOriginX;
- y4 += worldOriginY;
-
- float u1, v1, u2, v2, u3, v3, u4, v4;
- if (clockwise) {
- u1 = region.getU2();
- v1 = region.getV2();
- u2 = region.getU();
- v2 = region.getV2();
- u3 = region.getU();
- v3 = region.getV();
- u4 = region.getU2();
- v4 = region.getV();
- } else {
- u1 = region.getU();
- v1 = region.getV();
- u2 = region.getU2();
- v2 = region.getV();
- u3 = region.getU2();
- v3 = region.getV2();
- u4 = region.getU();
- v4 = region.getV2();
- }
-
- float color = this.colorPacked;
-
- vertices[idx++] = x1;
- vertices[idx++] = y1;
- vertices[idx++] = color;
- vertices[idx++] = u1;
- vertices[idx++] = v1;
- vertices[idx++] = ti;
-
- vertices[idx++] = x2;
- vertices[idx++] = y2;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = x3;
- vertices[idx++] = y3;
- vertices[idx++] = color;
- vertices[idx++] = u3;
- vertices[idx++] = v3;
- vertices[idx++] = ti;
-
- vertices[idx++] = x4;
- vertices[idx++] = y4;
- vertices[idx++] = color;
- vertices[idx++] = u4;
- vertices[idx++] = v4;
- vertices[idx++] = ti;
- }
-
- @Override
- public void draw (TextureRegion region, float width, float height, Affine2 transform) {
- if (!drawing) throw new IllegalStateException("TextureArraySpriteBatch.begin must be called before draw.");
-
- float[] vertices = this.vertices;
-
- flushIfFull();
-
- final float ti = activateTexture(region.getTexture());
-
- // construct corner points
- float x1 = transform.m02;
- float y1 = transform.m12;
- float x2 = transform.m01 * height + transform.m02;
- float y2 = transform.m11 * height + transform.m12;
- float x3 = transform.m00 * width + transform.m01 * height + transform.m02;
- float y3 = transform.m10 * width + transform.m11 * height + transform.m12;
- float x4 = transform.m00 * width + transform.m02;
- float y4 = transform.m10 * width + transform.m12;
-
- float u = region.getU();
- float v = region.getV2();
- float u2 = region.getU2();
- float v2 = region.getV();
-
- float color = this.colorPacked;
-
- vertices[idx++] = x1;
- vertices[idx++] = y1;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v;
- vertices[idx++] = ti;
-
- vertices[idx++] = x2;
- vertices[idx++] = y2;
- vertices[idx++] = color;
- vertices[idx++] = u;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = x3;
- vertices[idx++] = y3;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v2;
- vertices[idx++] = ti;
-
- vertices[idx++] = x4;
- vertices[idx++] = y4;
- vertices[idx++] = color;
- vertices[idx++] = u2;
- vertices[idx++] = v;
- vertices[idx++] = ti;
- }
-
- /** Flushes if the vertices array cannot hold an additional sprite ((spriteVertexSize + 1) * 4 vertices) anymore. */
- private void flushIfFull () {
- // original Sprite attribute size plus one extra float per sprite vertex
- if (vertices.length - idx < spriteSize) {
- flush();
- }
- }
-
- @Override
- public void flush () {
-
- if (idx == 0) return;
-
- renderCalls++;
- totalRenderCalls++;
-
- int spritesInBatch = idx / spriteSize;
- if (spritesInBatch > maxSpritesInBatch) maxSpritesInBatch = spritesInBatch;
- int count = spritesInBatch * 6;
-
- // Bind the textures
- for (int i = 0; i < currentTextureLFUSize; i++) {
- usedTextures[i].bind(i);
- }
-
- // Set TEXTURE0 as active again before drawing.
- Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0);
-
- Mesh mesh = this.mesh;
-
- mesh.setVertices(vertices, 0, idx);
-
- ((Buffer) mesh.getIndicesBuffer()).position(0);
- ((Buffer) mesh.getIndicesBuffer()).limit(count);
-
- if (blendingDisabled) {
- Gdx.gl.glDisable(GL20.GL_BLEND);
- } else {
- Gdx.gl.glEnable(GL20.GL_BLEND);
- if (blendSrcFunc != -1) Gdx.gl.glBlendFuncSeparate(blendSrcFunc, blendDstFunc, blendSrcFuncAlpha, blendDstFuncAlpha);
- }
-
- if (customShader != null) {
- mesh.render(customShader, GL20.GL_TRIANGLES, 0, count);
- } else {
- mesh.render(shader, GL20.GL_TRIANGLES, 0, count);
- }
-
- idx = 0;
- }
-
- /** Assigns Texture units and manages the LFU cache.
- * @param texture The texture that shall be loaded into the cache, if it is not already loaded.
- * @return The texture slot that has been allocated to the selected texture */
- private int activateTexture (Texture texture) {
-
- invTexWidth = 1.0f / texture.getWidth();
- invTexHeight = 1.0f / texture.getHeight();
-
- // This is our identifier for the textures
- final int textureHandle = texture.getTextureObjectHandle();
-
- // First try to see if the texture is already cached
- for (int i = 0; i < currentTextureLFUSize; i++) {
-
- // getTextureObjectHandle() just returns an int,
- // it's fine to call this method instead of caching the value.
- if (textureHandle == usedTextures[i].getTextureObjectHandle()) {
-
- // Increase the access counter.
- usedTexturesLFU[i]++;
-
- return i;
- }
- }
-
- // If a free texture unit is available we just use it
- // If not we have to flush and then throw out the least accessed one.
- if (currentTextureLFUSize < maxTextureUnits) {
-
- // Put the texture into the next free slot
- usedTextures[currentTextureLFUSize] = texture;
-
- // Increase the access counter.
- usedTexturesLFU[currentTextureLFUSize]++;
-
- return currentTextureLFUSize++;
-
- } else {
-
- // We have to flush if there is something in the pipeline already,
- // otherwise the texture index of previously rendered sprites gets invalidated
- if (idx > 0) {
- flush();
- }
-
- int slot = 0;
- int slotVal = usedTexturesLFU[0];
-
- int max = 0;
- int average = 0;
-
- // We search for the best candidate for a swap (least accessed) and collect some data
- for (int i = 0; i < maxTextureUnits; i++) {
-
- final int val = usedTexturesLFU[i];
-
- max = Math.max(val, max);
-
- average += val;
-
- if (val <= slotVal) {
- slot = i;
- slotVal = val;
- }
- }
-
- // The LFU weights will be normalized to the range 0...100
- final int normalizeRange = 100;
-
- for (int i = 0; i < maxTextureUnits; i++) {
- usedTexturesLFU[i] = usedTexturesLFU[i] * normalizeRange / max;
- }
-
- average = (average * normalizeRange) / (max * maxTextureUnits);
-
- // Give the new texture a fair (average) chance of staying.
- usedTexturesLFU[slot] = average;
-
- usedTextures[slot] = texture;
-
- // For statistics
- currentTextureLFUSwaps++;
-
- return slot;
- }
- }
-
- /** @return The number of texture swaps the LFU cache performed since calling {@link#begin()}. */
- public int getTextureLFUSwaps () {
- return currentTextureLFUSwaps;
- }
-
- /** @return The current number of textures in the LFU cache. Gets reset when calling {@link#begin()}. */
- public int getTextureLFUSize () {
- return currentTextureLFUSize;
- }
-
- /** @return The maximum number of textures that the LFU cache can hold. This limit is imposed by the driver.
- * @see {@link #getMaxTextureUnits()} */
- public int getTextureLFUCapacity () {
- return getMaxTextureUnits();
- }
-
- @Override
- public void disableBlending () {
-
- if (blendingDisabled) return;
-
- flush();
-
- blendingDisabled = true;
- }
-
- @Override
- public void enableBlending () {
-
- if (!blendingDisabled) {
- return;
- }
-
- flush();
-
- blendingDisabled = false;
- }
-
- @Override
- public void setBlendFunction (int srcFunc, int dstFunc) {
- setBlendFunctionSeparate(srcFunc, dstFunc, srcFunc, dstFunc);
- }
-
- @Override
- public void setBlendFunctionSeparate (int srcFuncColor, int dstFuncColor, int srcFuncAlpha, int dstFuncAlpha) {
-
- if (blendSrcFunc == srcFuncColor && blendDstFunc == dstFuncColor && blendSrcFuncAlpha == srcFuncAlpha
- && blendDstFuncAlpha == dstFuncAlpha) {
- return;
- }
-
- flush();
-
- blendSrcFunc = srcFuncColor;
- blendDstFunc = dstFuncColor;
- blendSrcFuncAlpha = srcFuncAlpha;
- blendDstFuncAlpha = dstFuncAlpha;
- }
-
- @Override
- public int getBlendSrcFunc () {
- return blendSrcFunc;
- }
-
- @Override
- public int getBlendDstFunc () {
- return blendDstFunc;
- }
-
- @Override
- public int getBlendSrcFuncAlpha () {
- return blendSrcFuncAlpha;
- }
-
- @Override
- public int getBlendDstFuncAlpha () {
- return blendDstFuncAlpha;
- }
-
- @Override
- public boolean isBlendingEnabled () {
- return !blendingDisabled;
- }
-
- @Override
- public boolean isDrawing () {
- return drawing;
- }
-
- @Override
- public Matrix4 getProjectionMatrix () {
- return projectionMatrix;
- }
-
- @Override
- public Matrix4 getTransformMatrix () {
- return transformMatrix;
- }
-
- @Override
- public void setProjectionMatrix (Matrix4 projection) {
-
- if (drawing) {
- flush();
- }
-
- projectionMatrix.set(projection);
-
- if (drawing) {
- setupMatrices();
- }
- }
-
- @Override
- public void setTransformMatrix (Matrix4 transform) {
-
- if (drawing) {
- flush();
- }
-
- transformMatrix.set(transform);
-
- if (drawing) {
- setupMatrices();
- }
- }
-
- private void setupMatrices () {
-
- combinedMatrix.set(projectionMatrix).mul(transformMatrix);
-
- if (customShader != null) {
- customShader.setUniformMatrix("u_projTrans", combinedMatrix);
- Gdx.gl20.glUniform1iv(customShader.fetchUniformLocation("u_textures", true), maxTextureUnits, textureUnitIndicesBuffer);
-
- } else {
- shader.setUniformMatrix("u_projTrans", combinedMatrix);
- Gdx.gl20.glUniform1iv(shader.fetchUniformLocation("u_textures", true), maxTextureUnits, textureUnitIndicesBuffer);
- }
- }
-
- /** Queries the number of supported textures in a texture array by trying the create the default shader.
- * The first call of this method is very expensive, after that it simply returns a cached value.
- * @return the number of supported textures in a texture array or zero if this feature is unsupported on this device.
- * @see {@link #setShader(ShaderProgram shader)} */
- public static int getMaxTextureUnits () {
-
- if (maxTextureUnits == -1) {
-
- // Query the number of available texture units and decide on a safe number of texture units to use
- IntBuffer texUnitsQueryBuffer = BufferUtils.newIntBuffer(32);
-
- Gdx.gl.glGetIntegerv(GL20.GL_MAX_TEXTURE_IMAGE_UNITS, texUnitsQueryBuffer);
-
- int maxTextureUnitsLocal = texUnitsQueryBuffer.get();
-
- // Some OpenGL drivers (I'm looking at you, Intel!) do not report the right values,
- // so we take caution and test it first, reducing the number of slots if needed.
- // Will try to find the maximum amount of texture units supported.
- while (maxTextureUnitsLocal > 0) {
-
- try {
-
- ShaderProgram tempProg = createDefaultShader(maxTextureUnitsLocal);
-
- tempProg.dispose();
-
- break;
-
- } catch (Exception e) {
-
- maxTextureUnitsLocal /= 2;
-
- shaderErrorLog = e.getMessage();
- }
- }
-
- maxTextureUnits = maxTextureUnitsLocal;
- }
-
- return maxTextureUnits;
- }
-
- /** Sets the shader to be used in a GLES 2.0 environment. Vertex position attribute is called "a_position", the texture
- * coordinates attribute is called "a_texCoord0", the color attribute is called "a_color", texture unit index is called
- * "texture_index", this needs to be converted to int with int(...) in the fragment shader. See
- * {@link ShaderProgram#POSITION_ATTRIBUTE}, {@link ShaderProgram#COLOR_ATTRIBUTE} and {@link ShaderProgram#TEXCOORD_ATTRIBUTE}
- * which gets "0" appended to indicate the use of the first texture unit. The combined transform and projection matrix is
- * uploaded via a mat4 uniform called "u_projTrans". The texture sampler array is passed via a uniform called "u_textures", see
- * {@link TextureArraySpriteBatch#createDefaultShader(int)} for reference.
- *
- * Call this method with a null argument to use the default shader. - *
- * This method will flush the batch before setting the new shader, you can call it in between {@link #begin()} and - * {@link #end()}. - * @param shader the {@link ShaderProgram} or null to use the default shader. - * @See {@link#createDefaultShader()} {@link#getMaxTextureUnits()} */ - @Override - public void setShader (ShaderProgram shader) { - - if (drawing) { - - flush(); - - if (customShader != null) { - customShader.end(); - } else { - this.shader.end(); - } - } - - customShader = shader; - - if (drawing) { - - if (customShader != null) { - customShader.begin(); - } else { - this.shader.begin(); - } - - setupMatrices(); - } - } - - @Override - public ShaderProgram getShader () { - - if (customShader != null) { - return customShader; - } else { - return shader; - } - } -} diff --git a/core/src/com/unciv/ui/screens/basescreen/UncivStage.kt b/core/src/com/unciv/ui/screens/basescreen/UncivStage.kt index 2f0bb167c1..d1ac944f03 100644 --- a/core/src/com/unciv/ui/screens/basescreen/UncivStage.kt +++ b/core/src/com/unciv/ui/screens/basescreen/UncivStage.kt @@ -6,7 +6,6 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.math.Rectangle import com.badlogic.gdx.scenes.scene2d.Stage import com.badlogic.gdx.utils.viewport.Viewport -import com.unciv.UncivGame import com.unciv.logic.event.Event import com.unciv.logic.event.EventBus import com.unciv.ui.crashhandling.wrapCrashHandling @@ -18,18 +17,7 @@ import com.unciv.utils.Log class UncivStage(viewport: Viewport) : Stage(viewport, getBatch()) { companion object { - fun getBatch(size: Int=1000): Batch { - // If for some reason it fails, we resort to usual SpriteBatch - return if (UncivGame.Current.settings.experimentalRendering) { - try { - TextureArraySpriteBatch(size) - } catch (e: Exception) { - SpriteBatch(size) - } - } else { - SpriteBatch(size) - } - } + fun getBatch(size: Int=1000): Batch = SpriteBatch(size) } /**