diff --git a/src/com/badlogic/gdx/graphics/g2d/UnpackedColourSpriteBatch.java b/src/com/badlogic/gdx/graphics/g2d/UnpackedColourSpriteBatch.java new file mode 100644 index 000000000..681b36333 --- /dev/null +++ b/src/com/badlogic/gdx/graphics/g2d/UnpackedColourSpriteBatch.java @@ -0,0 +1,1376 @@ +package com.badlogic.gdx.graphics.g2d; + + +/******************************************************************************* + * Copyright 2011 See AUTHORS file. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + + +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.glutils.ShaderProgram; +import com.badlogic.gdx.math.Affine2; +import com.badlogic.gdx.math.MathUtils; +import com.badlogic.gdx.math.Matrix4; +import net.torvald.gdx.graphics.Cvec; + +import java.nio.Buffer; + +/** Draws batched quads using indices. + * Created by minjaesong on 2023-09-14. + * @see Batch + * @author mzechner + * @author Nathan Sweet + * @author CuriousTorvald + */ +public class UnpackedColourSpriteBatch extends SpriteBatch { + /** @deprecated Do not use, this field is for testing only and is likely to be removed. Sets the {@link VertexDataType} to be + * used when gles 3 is not available, defaults to {@link VertexDataType#VertexArray}. */ + @Deprecated public static VertexDataType defaultVertexDataType = VertexDataType.VertexArray; + + private Mesh mesh; + + final float[] vertices; + int idx = 0; + Texture lastTexture = null; + float invTexWidth = 0, invTexHeight = 0; + + 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 final ShaderProgram shader; + private ShaderProgram customShader = null; + private boolean ownsShader; + + private final Color color = new Color(1, 1, 1, 1); + private final Cvec generic = new Cvec(0); + 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; + + /** Constructs a new SpriteBatch with a size of 1000, one buffer, and the default shader. + * @see SpriteBatch#SpriteBatch(int, ShaderProgram) */ + public UnpackedColourSpriteBatch () { + this(1000, null); + } + + /** Constructs a SpriteBatch with one buffer and the default shader. + * @see SpriteBatch#SpriteBatch(int, ShaderProgram) */ + public UnpackedColourSpriteBatch (int size) { + this(size, null); + } + + /** Constructs a new SpriteBatch. 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)}. See {@link #createDefaultShader()}. + * @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 SpriteBatch and must be disposed separately. */ + public UnpackedColourSpriteBatch (int size, ShaderProgram defaultShader) { + // 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); + + VertexDataType vertexDataType = (Gdx.gl30 != null) ? VertexDataType.VertexBufferObjectWithVAO : defaultVertexDataType; + + mesh = new Mesh(vertexDataType, false, size * 4, size * 6, + new VertexAttribute(Usage.Position, 2, "a_position"), + new VertexAttribute(Usage.ColorUnpacked, 4, "a_color"), + new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoord0"), + new VertexAttribute(Usage.Generic, 4, "a_generic")); + + projectionMatrix.setToOrtho2D(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + + vertices = new float[size * 4 * 8]; + + 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); + + if (defaultShader == null) { + shader = createDefaultShader(); + ownsShader = true; + } else + shader = defaultShader; + } + + /** Returns a new instance of the default shader used by SpriteBatch for GL2 when no shader is specified. */ + static public ShaderProgram createDefaultShader () { + String vertexShader = """ + #version 150 + + in vec4 a_position; + in vec4 a_color; + in vec4 a_generic; + in vec2 a_texCoord0; + + uniform mat4 u_projTrans; + + out vec4 v_color; + out vec2 v_texCoords; + out vec4 v_generic; + + void main() { + v_color = a_color; + v_texCoords = a_texCoord0; + v_generic = a_generic; + gl_Position = u_projTrans * a_position; + }"""; + String fragmentShader = """ + #version 150 + + #ifdef GL_ES + precision mediump float; + #endif + + in vec4 v_color; + in vec4 v_generic; + in vec2 v_texCoords; + uniform sampler2D u_texture; + out vec4 fragColor; + + void main() { + fragColor = v_color * texture(u_texture, v_texCoords); + }"""; + + 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("SpriteBatch.end must be called before begin."); + renderCalls = 0; + + Gdx.gl.glDepthMask(false); + if (customShader != null) + customShader.bind(); + else + shader.bind(); + setupMatrices(); + + drawing = true; + } + + @Override + public void end () { + if (!drawing) throw new IllegalStateException("SpriteBatch.begin must be called before end."); + if (idx > 0) flush(); + lastTexture = null; + drawing = false; + + GL20 gl = Gdx.gl; + gl.glDepthMask(true); + if (isBlendingEnabled()) gl.glDisable(GL20.GL_BLEND); + } + + @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; + } + + + public void setGeneric (Cvec xyzw) { + generic.set(xyzw); + } + + public void setGeneric (float x, float y, float z, float w) { + generic.set(x, y, z, w); + } + + public Cvec getGeneric () { + return generic; + } + + @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("SpriteBatch.begin must be called before draw."); + + float[] vertices = this.vertices; + + if (texture != lastTexture) + switchTexture(texture); + else if (idx == vertices.length) // + flush(); + + // 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; + } + + int idx = this.idx; + vertices[idx] = x1; + vertices[idx + 1] = y1; + vertices[idx + 2] = color.r; + vertices[idx + 3] = color.g; + vertices[idx + 4] = color.b; + vertices[idx + 5] = color.a; + vertices[idx + 6] = u; + vertices[idx + 7] = v; + vertices[idx + 8] = generic.r; + vertices[idx + 9] = generic.g; + vertices[idx + 10] = generic.b; + vertices[idx + 11] = generic.a; + + vertices[idx + 12] = x2; + vertices[idx + 13] = y2; + vertices[idx + 14] = color.r; + vertices[idx + 15] = color.g; + vertices[idx + 16] = color.b; + vertices[idx + 17] = color.a; + vertices[idx + 18] = u; + vertices[idx + 19] = v2; + vertices[idx + 20] = generic.r; + vertices[idx + 21] = generic.g; + vertices[idx + 22] = generic.b; + vertices[idx + 23] = generic.a; + + vertices[idx + 24] = x3; + vertices[idx + 25] = y3; + vertices[idx + 26] = color.r; + vertices[idx + 27] = color.g; + vertices[idx + 28] = color.b; + vertices[idx + 29] = color.a; + vertices[idx + 30] = u2; + vertices[idx + 31] = v2; + vertices[idx + 32] = generic.r; + vertices[idx + 33] = generic.g; + vertices[idx + 34] = generic.b; + vertices[idx + 35] = generic.a; + + vertices[idx + 36] = x4; + vertices[idx + 37] = y4; + vertices[idx + 38] = color.r; + vertices[idx + 39] = color.g; + vertices[idx + 40] = color.b; + vertices[idx + 41] = color.a; + vertices[idx + 42] = u2; + vertices[idx + 43] = v; + vertices[idx + 44] = generic.r; + vertices[idx + 45] = generic.g; + vertices[idx + 46] = generic.b; + vertices[idx + 47] = generic.a; + this.idx = idx + 48; + } + + @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("SpriteBatch.begin must be called before draw."); + + float[] vertices = this.vertices; + + if (texture != lastTexture) + switchTexture(texture); + else if (idx == vertices.length) // + flush(); + + 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; + } + + int idx = this.idx; + vertices[idx] = x; + vertices[idx + 1] = y; + vertices[idx + 2] = color.r; + vertices[idx + 3] = color.g; + vertices[idx + 4] = color.b; + vertices[idx + 5] = color.a; + vertices[idx + 6] = u; + vertices[idx + 7] = v; + vertices[idx + 8] = generic.r; + vertices[idx + 9] = generic.g; + vertices[idx + 10] = generic.b; + vertices[idx + 11] = generic.a; + + vertices[idx + 12] = x; + vertices[idx + 13] = fy2; + vertices[idx + 14] = color.r; + vertices[idx + 15] = color.g; + vertices[idx + 16] = color.b; + vertices[idx + 17] = color.a; + vertices[idx + 18] = u; + vertices[idx + 19] = v2; + vertices[idx + 20] = generic.r; + vertices[idx + 21] = generic.g; + vertices[idx + 22] = generic.b; + vertices[idx + 23] = generic.a; + + vertices[idx + 24] = fx2; + vertices[idx + 25] = fy2; + vertices[idx + 26] = color.r; + vertices[idx + 27] = color.g; + vertices[idx + 28] = color.b; + vertices[idx + 29] = color.a; + vertices[idx + 30] = u2; + vertices[idx + 31] = v2; + vertices[idx + 32] = generic.r; + vertices[idx + 33] = generic.g; + vertices[idx + 34] = generic.b; + vertices[idx + 35] = generic.a; + + vertices[idx + 36] = fx2; + vertices[idx + 37] = y; + vertices[idx + 38] = color.r; + vertices[idx + 39] = color.g; + vertices[idx + 40] = color.b; + vertices[idx + 41] = color.a; + vertices[idx + 42] = u2; + vertices[idx + 43] = v; + vertices[idx + 44] = generic.r; + vertices[idx + 45] = generic.g; + vertices[idx + 46] = generic.b; + vertices[idx + 47] = generic.a; + this.idx = idx + 48; + } + + @Override + public void draw (Texture texture, float x, float y, int srcX, int srcY, int srcWidth, int srcHeight) { + if (!drawing) throw new IllegalStateException("SpriteBatch.begin must be called before draw."); + + float[] vertices = this.vertices; + + if (texture != lastTexture) + switchTexture(texture); + else if (idx == vertices.length) // + flush(); + + 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; + + int idx = this.idx; + vertices[idx] = x; + vertices[idx + 1] = y; + vertices[idx + 2] = color.r; + vertices[idx + 3] = color.g; + vertices[idx + 4] = color.b; + vertices[idx + 5] = color.a; + vertices[idx + 6] = u; + vertices[idx + 7] = v; + vertices[idx + 8] = generic.r; + vertices[idx + 9] = generic.g; + vertices[idx + 10] = generic.b; + vertices[idx + 11] = generic.a; + + vertices[idx + 12] = x; + vertices[idx + 13] = fy2; + vertices[idx + 14] = color.r; + vertices[idx + 15] = color.g; + vertices[idx + 16] = color.b; + vertices[idx + 17] = color.a; + vertices[idx + 18] = u; + vertices[idx + 19] = v2; + vertices[idx + 20] = generic.r; + vertices[idx + 21] = generic.g; + vertices[idx + 22] = generic.b; + vertices[idx + 23] = generic.a; + + vertices[idx + 24] = fx2; + vertices[idx + 25] = fy2; + vertices[idx + 26] = color.r; + vertices[idx + 27] = color.g; + vertices[idx + 28] = color.b; + vertices[idx + 29] = color.a; + vertices[idx + 30] = u2; + vertices[idx + 31] = v2; + vertices[idx + 32] = generic.r; + vertices[idx + 33] = generic.g; + vertices[idx + 34] = generic.b; + vertices[idx + 35] = generic.a; + + vertices[idx + 36] = fx2; + vertices[idx + 37] = y; + vertices[idx + 38] = color.r; + vertices[idx + 39] = color.g; + vertices[idx + 40] = color.b; + vertices[idx + 41] = color.a; + vertices[idx + 42] = u2; + vertices[idx + 43] = v; + vertices[idx + 44] = generic.r; + vertices[idx + 45] = generic.g; + vertices[idx + 46] = generic.b; + vertices[idx + 47] = generic.a; + this.idx = idx + 48; + } + + @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("SpriteBatch.begin must be called before draw."); + + float[] vertices = this.vertices; + + if (texture != lastTexture) + switchTexture(texture); + else if (idx == vertices.length) // + flush(); + + final float fx2 = x + width; + final float fy2 = y + height; + + int idx = this.idx; + vertices[idx] = x; + vertices[idx + 1] = y; + vertices[idx + 2] = color.r; + vertices[idx + 3] = color.g; + vertices[idx + 4] = color.b; + vertices[idx + 5] = color.a; + vertices[idx + 6] = u; + vertices[idx + 7] = v; + vertices[idx + 8] = generic.r; + vertices[idx + 9] = generic.g; + vertices[idx + 10] = generic.b; + vertices[idx + 11] = generic.a; + + vertices[idx + 12] = x; + vertices[idx + 13] = fy2; + vertices[idx + 14] = color.r; + vertices[idx + 15] = color.g; + vertices[idx + 16] = color.b; + vertices[idx + 17] = color.a; + vertices[idx + 18] = u; + vertices[idx + 19] = v2; + vertices[idx + 20] = generic.r; + vertices[idx + 21] = generic.g; + vertices[idx + 22] = generic.b; + vertices[idx + 23] = generic.a; + + vertices[idx + 24] = fx2; + vertices[idx + 25] = fy2; + vertices[idx + 26] = color.r; + vertices[idx + 27] = color.g; + vertices[idx + 28] = color.b; + vertices[idx + 29] = color.a; + vertices[idx + 30] = u2; + vertices[idx + 31] = v2; + vertices[idx + 32] = generic.r; + vertices[idx + 33] = generic.g; + vertices[idx + 34] = generic.b; + vertices[idx + 35] = generic.a; + + vertices[idx + 36] = fx2; + vertices[idx + 37] = y; + vertices[idx + 38] = color.r; + vertices[idx + 39] = color.g; + vertices[idx + 40] = color.b; + vertices[idx + 41] = color.a; + vertices[idx + 42] = u2; + vertices[idx + 43] = v; + vertices[idx + 44] = generic.r; + vertices[idx + 45] = generic.g; + vertices[idx + 46] = generic.b; + vertices[idx + 47] = generic.a; + this.idx = idx + 48; + } + + @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("SpriteBatch.begin must be called before draw."); + + float[] vertices = this.vertices; + + if (texture != lastTexture) + switchTexture(texture); + else if (idx == vertices.length) // + flush(); + + 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; + + int idx = this.idx; + vertices[idx] = x; + vertices[idx + 1] = y; + vertices[idx + 2] = color.r; + vertices[idx + 3] = color.g; + vertices[idx + 4] = color.b; + vertices[idx + 5] = color.a; + vertices[idx + 6] = u; + vertices[idx + 7] = v; + vertices[idx + 8] = generic.r; + vertices[idx + 9] = generic.g; + vertices[idx + 10] = generic.b; + vertices[idx + 11] = generic.a; + + vertices[idx + 12] = x; + vertices[idx + 13] = fy2; + vertices[idx + 14] = color.r; + vertices[idx + 15] = color.g; + vertices[idx + 16] = color.b; + vertices[idx + 17] = color.a; + vertices[idx + 18] = u; + vertices[idx + 19] = v2; + vertices[idx + 20] = generic.r; + vertices[idx + 21] = generic.g; + vertices[idx + 22] = generic.b; + vertices[idx + 23] = generic.a; + + vertices[idx + 24] = fx2; + vertices[idx + 25] = fy2; + vertices[idx + 26] = color.r; + vertices[idx + 27] = color.g; + vertices[idx + 28] = color.b; + vertices[idx + 29] = color.a; + vertices[idx + 30] = u2; + vertices[idx + 31] = v2; + vertices[idx + 32] = generic.r; + vertices[idx + 33] = generic.g; + vertices[idx + 34] = generic.b; + vertices[idx + 35] = generic.a; + + vertices[idx + 36] = fx2; + vertices[idx + 37] = y; + vertices[idx + 38] = color.r; + vertices[idx + 39] = color.g; + vertices[idx + 40] = color.b; + vertices[idx + 41] = color.a; + vertices[idx + 42] = u2; + vertices[idx + 43] = v; + vertices[idx + 44] = generic.r; + vertices[idx + 45] = generic.g; + vertices[idx + 46] = generic.b; + vertices[idx + 47] = generic.a; + this.idx = idx + 48; + } + + @Override + public void draw (Texture texture, float[] spriteVertices, int offset, int count) { + if (!drawing) throw new IllegalStateException("SpriteBatch.begin must be called before draw."); + + int verticesLength = vertices.length; + int remainingVertices = verticesLength; + if (texture != lastTexture) + switchTexture(texture); + else { + remainingVertices -= idx; + if (remainingVertices == 0) { + flush(); + remainingVertices = verticesLength; + } + } + int copyCount = Math.min(remainingVertices, count); + + System.arraycopy(spriteVertices, offset, vertices, idx, copyCount); + idx += copyCount; + count -= copyCount; + while (count > 0) { + offset += copyCount; + flush(); + copyCount = Math.min(verticesLength, count); + System.arraycopy(spriteVertices, offset, vertices, 0, copyCount); + idx += copyCount; + count -= copyCount; + } + } + + @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("SpriteBatch.begin must be called before draw."); + + float[] vertices = this.vertices; + + Texture texture = region.texture; + if (texture != lastTexture) { + switchTexture(texture); + } else if (idx == vertices.length) // + flush(); + + final float fx2 = x + width; + final float fy2 = y + height; + final float u = region.u; + final float v = region.v2; + final float u2 = region.u2; + final float v2 = region.v; + + int idx = this.idx; + vertices[idx] = x; + vertices[idx + 1] = y; + vertices[idx + 2] = color.r; + vertices[idx + 3] = color.g; + vertices[idx + 4] = color.b; + vertices[idx + 5] = color.a; + vertices[idx + 6] = u; + vertices[idx + 7] = v; + vertices[idx + 8] = generic.r; + vertices[idx + 9] = generic.g; + vertices[idx + 10] = generic.b; + vertices[idx + 11] = generic.a; + + vertices[idx + 12] = x; + vertices[idx + 13] = fy2; + vertices[idx + 14] = color.r; + vertices[idx + 15] = color.g; + vertices[idx + 16] = color.b; + vertices[idx + 17] = color.a; + vertices[idx + 18] = u; + vertices[idx + 19] = v2; + vertices[idx + 20] = generic.r; + vertices[idx + 21] = generic.g; + vertices[idx + 22] = generic.b; + vertices[idx + 23] = generic.a; + + vertices[idx + 24] = fx2; + vertices[idx + 25] = fy2; + vertices[idx + 26] = color.r; + vertices[idx + 27] = color.g; + vertices[idx + 28] = color.b; + vertices[idx + 29] = color.a; + vertices[idx + 30] = u2; + vertices[idx + 31] = v2; + vertices[idx + 32] = generic.r; + vertices[idx + 33] = generic.g; + vertices[idx + 34] = generic.b; + vertices[idx + 35] = generic.a; + + vertices[idx + 36] = fx2; + vertices[idx + 37] = y; + vertices[idx + 38] = color.r; + vertices[idx + 39] = color.g; + vertices[idx + 40] = color.b; + vertices[idx + 41] = color.a; + vertices[idx + 42] = u2; + vertices[idx + 43] = v; + vertices[idx + 44] = generic.r; + vertices[idx + 45] = generic.g; + vertices[idx + 46] = generic.b; + vertices[idx + 47] = generic.a; + this.idx = idx + 48; + } + + @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("SpriteBatch.begin must be called before draw."); + + float[] vertices = this.vertices; + + Texture texture = region.texture; + if (texture != lastTexture) { + switchTexture(texture); + } else if (idx == vertices.length) // + flush(); + + // 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.u; + final float v = region.v2; + final float u2 = region.u2; + final float v2 = region.v; + + int idx = this.idx; + vertices[idx] = x1; + vertices[idx + 1] = y1; + vertices[idx + 2] = color.r; + vertices[idx + 3] = color.g; + vertices[idx + 4] = color.b; + vertices[idx + 5] = color.a; + vertices[idx + 6] = u; + vertices[idx + 7] = v; + vertices[idx + 8] = generic.r; + vertices[idx + 9] = generic.g; + vertices[idx + 10] = generic.b; + vertices[idx + 11] = generic.a; + + vertices[idx + 12] = x2; + vertices[idx + 13] = y2; + vertices[idx + 14] = color.r; + vertices[idx + 15] = color.g; + vertices[idx + 16] = color.b; + vertices[idx + 17] = color.a; + vertices[idx + 18] = u; + vertices[idx + 19] = v2; + vertices[idx + 20] = generic.r; + vertices[idx + 21] = generic.g; + vertices[idx + 22] = generic.b; + vertices[idx + 23] = generic.a; + + vertices[idx + 24] = x3; + vertices[idx + 25] = y3; + vertices[idx + 26] = color.r; + vertices[idx + 27] = color.g; + vertices[idx + 28] = color.b; + vertices[idx + 29] = color.a; + vertices[idx + 30] = u2; + vertices[idx + 31] = v2; + vertices[idx + 32] = generic.r; + vertices[idx + 33] = generic.g; + vertices[idx + 34] = generic.b; + vertices[idx + 35] = generic.a; + + vertices[idx + 36] = x4; + vertices[idx + 37] = y4; + vertices[idx + 38] = color.r; + vertices[idx + 39] = color.g; + vertices[idx + 40] = color.b; + vertices[idx + 41] = color.a; + vertices[idx + 42] = u2; + vertices[idx + 43] = v; + vertices[idx + 44] = generic.r; + vertices[idx + 45] = generic.g; + vertices[idx + 46] = generic.b; + vertices[idx + 47] = generic.a; + this.idx = idx + 48; + } + + @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("SpriteBatch.begin must be called before draw."); + + float[] vertices = this.vertices; + + Texture texture = region.texture; + if (texture != lastTexture) { + switchTexture(texture); + } else if (idx == vertices.length) // + flush(); + + // 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.u2; + v1 = region.v2; + u2 = region.u; + v2 = region.v2; + u3 = region.u; + v3 = region.v; + u4 = region.u2; + v4 = region.v; + } else { + u1 = region.u; + v1 = region.v; + u2 = region.u2; + v2 = region.v; + u3 = region.u2; + v3 = region.v2; + u4 = region.u; + v4 = region.v2; + } + + int idx = this.idx; + vertices[idx] = x1; + vertices[idx + 1] = y1; + vertices[idx + 2] = color.r; + vertices[idx + 3] = color.g; + vertices[idx + 4] = color.b; + vertices[idx + 5] = color.a; + vertices[idx + 6] = u1; + vertices[idx + 7] = v1; + vertices[idx + 8] = generic.r; + vertices[idx + 9] = generic.g; + vertices[idx + 10] = generic.b; + vertices[idx + 11] = generic.a; + + vertices[idx + 12] = x2; + vertices[idx + 13] = y2; + vertices[idx + 14] = color.r; + vertices[idx + 15] = color.g; + vertices[idx + 16] = color.b; + vertices[idx + 17] = color.a; + vertices[idx + 18] = u2; + vertices[idx + 19] = v2; + vertices[idx + 20] = generic.r; + vertices[idx + 21] = generic.g; + vertices[idx + 22] = generic.b; + vertices[idx + 23] = generic.a; + + vertices[idx + 24] = x3; + vertices[idx + 25] = y3; + vertices[idx + 26] = color.r; + vertices[idx + 27] = color.g; + vertices[idx + 28] = color.b; + vertices[idx + 29] = color.a; + vertices[idx + 30] = u3; + vertices[idx + 31] = v3; + vertices[idx + 32] = generic.r; + vertices[idx + 33] = generic.g; + vertices[idx + 34] = generic.b; + vertices[idx + 35] = generic.a; + + vertices[idx + 36] = x4; + vertices[idx + 37] = y4; + vertices[idx + 38] = color.r; + vertices[idx + 39] = color.g; + vertices[idx + 40] = color.b; + vertices[idx + 41] = color.a; + vertices[idx + 42] = u4; + vertices[idx + 43] = v4; + vertices[idx + 44] = generic.r; + vertices[idx + 45] = generic.g; + vertices[idx + 46] = generic.b; + vertices[idx + 47] = generic.a; + this.idx = idx + 48; + } + + @Override + public void draw (TextureRegion region, float width, float height, Affine2 transform) { + if (!drawing) throw new IllegalStateException("SpriteBatch.begin must be called before draw."); + + float[] vertices = this.vertices; + + Texture texture = region.texture; + if (texture != lastTexture) { + switchTexture(texture); + } else if (idx == vertices.length) { + flush(); + } + + // 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.u; + float v = region.v2; + float u2 = region.u2; + float v2 = region.v; + + int idx = this.idx; + vertices[idx] = x1; + vertices[idx + 1] = y1; + vertices[idx + 2] = color.r; + vertices[idx + 3] = color.g; + vertices[idx + 4] = color.b; + vertices[idx + 5] = color.a; + vertices[idx + 6] = u; + vertices[idx + 7] = v; + vertices[idx + 8] = generic.r; + vertices[idx + 9] = generic.g; + vertices[idx + 10] = generic.b; + vertices[idx + 11] = generic.a; + + vertices[idx + 12] = x2; + vertices[idx + 13] = y2; + vertices[idx + 14] = color.r; + vertices[idx + 15] = color.g; + vertices[idx + 16] = color.b; + vertices[idx + 17] = color.a; + vertices[idx + 18] = u; + vertices[idx + 19] = v2; + vertices[idx + 20] = generic.r; + vertices[idx + 21] = generic.g; + vertices[idx + 22] = generic.b; + vertices[idx + 23] = generic.a; + + vertices[idx + 24] = x3; + vertices[idx + 25] = y3; + vertices[idx + 26] = color.r; + vertices[idx + 27] = color.g; + vertices[idx + 28] = color.b; + vertices[idx + 29] = color.a; + vertices[idx + 30] = u2; + vertices[idx + 31] = v2; + vertices[idx + 32] = generic.r; + vertices[idx + 33] = generic.g; + vertices[idx + 34] = generic.b; + vertices[idx + 35] = generic.a; + + vertices[idx + 36] = x4; + vertices[idx + 37] = y4; + vertices[idx + 38] = color.r; + vertices[idx + 39] = color.g; + vertices[idx + 40] = color.b; + vertices[idx + 41] = color.a; + vertices[idx + 42] = u2; + vertices[idx + 43] = v; + vertices[idx + 44] = generic.r; + vertices[idx + 45] = generic.g; + vertices[idx + 46] = generic.b; + vertices[idx + 47] = generic.a; + this.idx = idx + 48; + } + + @Override + public void flush () { + if (idx == 0) return; + + renderCalls++; + totalRenderCalls++; + int spritesInBatch = idx / 20; + if (spritesInBatch > maxSpritesInBatch) maxSpritesInBatch = spritesInBatch; + int count = spritesInBatch * 6; + + lastTexture.bind(); + 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); + } + + mesh.render(customShader != null ? customShader : shader, GL20.GL_TRIANGLES, 0, count); + + idx = 0; + } + + @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 void dispose () { + mesh.dispose(); + if (ownsShader && shader != null) shader.dispose(); + } + + @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(); + } + + protected void setupMatrices () { + combinedMatrix.set(projectionMatrix).mul(transformMatrix); + if (customShader != null) { + customShader.setUniformMatrix("u_projTrans", combinedMatrix); + customShader.setUniformi("u_texture", 0); + } else { + shader.setUniformMatrix("u_projTrans", combinedMatrix); + shader.setUniformi("u_texture", 0); + } + } + + protected void switchTexture (Texture texture) { + flush(); + lastTexture = texture; + invTexWidth = 1.0f / texture.getWidth(); + invTexHeight = 1.0f / texture.getHeight(); + } + + @Override + public void setShader (ShaderProgram shader) { + if (drawing) { + flush(); + } + customShader = shader; + if (drawing) { + if (customShader != null) + customShader.bind(); + else + this.shader.bind(); + setupMatrices(); + } + } + + @Override + public ShaderProgram getShader () { + if (customShader == null) { + return shader; + } + return customShader; + } + + @Override + public boolean isBlendingEnabled () { + return !blendingDisabled; + } + + public boolean isDrawing () { + return drawing; + } +} diff --git a/src/net/torvald/gdx/graphics/Cvec.kt b/src/net/torvald/gdx/graphics/Cvec.kt index d4e55de8c..5f6722bda 100644 --- a/src/net/torvald/gdx/graphics/Cvec.kt +++ b/src/net/torvald/gdx/graphics/Cvec.kt @@ -34,10 +34,15 @@ import com.badlogic.gdx.utils.NumberUtils class Cvec { /** the red, green, blue and alpha components */ - var r: Float = 0f - var g: Float = 0f - var b: Float = 0f - var a: Float = 0f + @kotlin.jvm.JvmField var r: Float = 0f + @kotlin.jvm.JvmField var g: Float = 0f + @kotlin.jvm.JvmField var b: Float = 0f + @kotlin.jvm.JvmField var a: Float = 0f + + var x: Float; get() = r; set(value) { r = value } + var y: Float; get() = g; set(value) { g = value } + var z: Float; get() = b; set(value) { b = value } + var w: Float; get() = a; set(value) { a = value } /** Constructs a new Cvec with all components set to 0. */ constructor() {} diff --git a/src/net/torvald/terrarum/FlippingSpriteBatch.kt b/src/net/torvald/terrarum/FlippingSpriteBatch.kt index 759aa96b8..2882c3ea4 100644 --- a/src/net/torvald/terrarum/FlippingSpriteBatch.kt +++ b/src/net/torvald/terrarum/FlippingSpriteBatch.kt @@ -3,13 +3,14 @@ package net.torvald.terrarum import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.TextureRegion +import com.badlogic.gdx.graphics.g2d.UnpackedColourSpriteBatch /** * Don't flip the assets! Flip the draw command instead! * * Created by minjaesong on 2021-12-13. */ -class FlippingSpriteBatch(size: Int = 1000) : SpriteBatch(size, DefaultGL32Shaders.createSpriteBatchShader()) { +class FlippingSpriteBatch(size: Int = 1000) : UnpackedColourSpriteBatch(size, DefaultGL32Shaders.createSpriteBatchShader()) { /** * This function draws the flipped version of the image by giving flipped uv-coord to the SpriteBatch @@ -42,6 +43,7 @@ class FlippingSpriteBatch(size: Int = 1000) : SpriteBatch(size, DefaultGL32Shade draw(region.texture, x, y, region.regionWidth.toFloat(), region.regionHeight.toFloat(), region.u, region.v2, region.u2, region.v) + /** * NOTE TO SELF: * diff --git a/src/net/torvald/terrarum/weather/WeatherMixer.kt b/src/net/torvald/terrarum/weather/WeatherMixer.kt index 88b67caed..dde381746 100644 --- a/src/net/torvald/terrarum/weather/WeatherMixer.kt +++ b/src/net/torvald/terrarum/weather/WeatherMixer.kt @@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx import com.badlogic.gdx.graphics.* import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.TextureRegion +import com.badlogic.gdx.graphics.g2d.UnpackedColourSpriteBatch import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.math.Vector3 import com.badlogic.gdx.utils.JsonValue @@ -518,7 +519,7 @@ internal object WeatherMixer : RNGConsumer { batch.shader.setUniformf("shadeCol", 0.06f, 0.07f, 0.08f, 1f) // TODO temporary value clouds.forEach { - it.render(batch, cloudDrawColour) + it.render(batch as UnpackedColourSpriteBatch, cloudDrawColour) } } } diff --git a/src/net/torvald/terrarum/weather/WeatherObjectCloud.kt b/src/net/torvald/terrarum/weather/WeatherObjectCloud.kt index 73f249ea8..3284f7435 100644 --- a/src/net/torvald/terrarum/weather/WeatherObjectCloud.kt +++ b/src/net/torvald/terrarum/weather/WeatherObjectCloud.kt @@ -3,6 +3,7 @@ package net.torvald.terrarum.weather import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.TextureRegion +import com.badlogic.gdx.graphics.g2d.UnpackedColourSpriteBatch import com.badlogic.gdx.math.Vector3 import com.jme3.math.FastMath import com.jme3.math.FastMath.PI @@ -77,28 +78,13 @@ class WeatherObjectCloud( private val vecMult = Vector3(1f, 1f, 1f / (4f * H)) - private fun roundRgbGamma(x: Float): Int { - return RGB_GAMMA_TABLE.mapIndexed { i, f -> (f - x).absoluteValue to i }.minBy { it.first }.second - } - private fun roundAgamma(x: Float): Int { - return A_GAMMA_TABLE.mapIndexed { i, f -> (f - x).absoluteValue to i }.minBy { it.first }.second - } - - fun render(batch: SpriteBatch, cloudDrawColour: Color) { + fun render(batch: UnpackedColourSpriteBatch, cloudDrawColour: Color) { val sc = screenCoord - val rgbGammaIndex = roundRgbGamma(rgbGamma) - val aGammaIndex = roundAgamma(aGamma) - // printdbg(this, "gamma: (${rgbGamma}, ${aGamma}) index: ($rgbGammaIndex, $aGammaIndex)") - val lightBits = cloudDrawColour.toIntBits() - val rbits = lightBits.ushr( 0).and(252) or rgbGammaIndex.ushr(2).and(3) - val gbits = lightBits.ushr( 8).and(252) or rgbGammaIndex.ushr(0).and(3) - val bbits = lightBits.ushr(16).and(252) or aGammaIndex - val abits = (alpha * 255).toInt() - - batch.color = Color(rbits.shl(24) or gbits.shl(16) or bbits.shl(8) or abits) + batch.color = cloudDrawColour + batch.generic.set(rgbGamma, aGamma, 0f, 0f) if (flipW) batch.draw(texture, sc.x + texture.regionWidth / posZ, sc.y, -texture.regionWidth * sc.z, texture.regionHeight * sc.z) @@ -182,31 +168,5 @@ class WeatherObjectCloud( const val CLOUD_STAGE_DEPTH = 256f const val OLD_AGE_DECAY = 5000f const val NEWBORN_GROWTH_TIME = 1000f - - val RGB_GAMMA_TABLE = floatArrayOf( - 0.2f, - 0.3f, - 0.4f, - 0.5f, - 0.6f, - 0.7f, - 0.8f, - 0.9f, - 1.0f, - 1.25f, - 1.5f, - 1.75f, - 2.0f, - 2.5f, - 3.0f, - 3.5f - ) - - val A_GAMMA_TABLE = floatArrayOf( - 1.6f, - 2.0f, - 2.4f, - 2.8f - ) } } \ No newline at end of file diff --git a/src/shaders/clouds.frag b/src/shaders/clouds.frag index c584482f3..0c6ff58f6 100644 --- a/src/shaders/clouds.frag +++ b/src/shaders/clouds.frag @@ -1,49 +1,15 @@ #version 400 -#ifdef GL_ES -#define LOWP lowp -precision mediump float; -#else -#define LOWP -#endif -in LOWP vec4 v_color; // lightCol.rgb + cloud's alpha +in vec4 v_color; // lightCol +in vec4 v_generic; // gamma values in vec2 v_texCoords; uniform sampler2D u_texture; out vec4 fragColor; const vec2 boolean = vec2(0.0, 1.0); -uniform LOWP vec4 shadeCol; - -const float rgbGammas[16] = float[]( -0.2, -0.3, -0.4, -0.5, - -0.6, -0.7, -0.8, -0.9, - -1.0, -1.25, -1.5, -1.75, - -2.0, -2.5, -3.0, -3.5 -); - -const float aGammas[4] = float[]( -1.6, -2.0, -2.4, -2.8 -); +uniform vec4 shadeCol; void main() { // vertex colour format: @@ -54,15 +20,10 @@ void main() { // bbbbbb: 6-bit blue component // MMLL: index to the rgbGammas // AA: index to the aGammas - vec4 cloudCol = vec4( - (int(v_color.r * 255) >> 2) * 4.0 / 255.0, - (int(v_color.g * 255) >> 2) * 4.0 / 255.0, - (int(v_color.b * 255) >> 2) * 4.0 / 255.0, - v_color.a - ); - float rgbGamma = rgbGammas[((int(v_color.r * 255) & 3) << 2) | (int(v_color.g * 255) & 3)]; - float aGamma = aGammas[int(v_color.b * 255) & 3]; - vec4 gamma = vec4(rgbGamma, rgbGamma, rgbGamma, aGamma); + vec4 cloudCol = v_color; + float rgbGamma = v_generic.x; + float aGamma = v_generic.y; + vec4 gamma = v_generic.xxxy; vec4 range = vec4(vec3(min(rgbGamma, 1.0 / rgbGamma)), 1.0); vec4 offset = vec4(vec3(max(0.0, 1.0 - rgbGamma)), 0.0); diff --git a/src/shaders/default.vert b/src/shaders/default.vert index 0a8a7a980..72733ceed 100644 --- a/src/shaders/default.vert +++ b/src/shaders/default.vert @@ -2,16 +2,18 @@ in vec4 a_position; in vec4 a_color; +in vec4 a_generic; in vec2 a_texCoord0; uniform mat4 u_projTrans; out vec4 v_color; out vec2 v_texCoords; +out vec4 v_generic; void main() { v_color = a_color; - v_color.a = v_color.a * (255.0/254.0); // GDX will crush the alpha value to 0,2,4,6,8,10,...,254; see com.badlogic.gdx.utils.NumberUtils.intToFloatColor v_texCoords = a_texCoord0; + v_generic = a_generic; gl_Position = u_projTrans * a_position; } \ No newline at end of file diff --git a/src/shaders/gl32spritebatch.frag b/src/shaders/gl32spritebatch.frag index 5cdf8c94c..0c7dd2d3a 100644 --- a/src/shaders/gl32spritebatch.frag +++ b/src/shaders/gl32spritebatch.frag @@ -1,13 +1,11 @@ #version 150 #ifdef GL_ES -#define LOWP lowp precision mediump float; -#else -#define LOWP #endif -in LOWP vec4 v_color; +in vec4 v_color; +in vec4 v_generic; in vec2 v_texCoords; uniform sampler2D u_texture; out vec4 fragColor; diff --git a/src/shaders/gl32spritebatch.vert b/src/shaders/gl32spritebatch.vert index b02f596f7..72733ceed 100644 --- a/src/shaders/gl32spritebatch.vert +++ b/src/shaders/gl32spritebatch.vert @@ -2,16 +2,18 @@ in vec4 a_position; in vec4 a_color; +in vec4 a_generic; in vec2 a_texCoord0; uniform mat4 u_projTrans; out vec4 v_color; out vec2 v_texCoords; +out vec4 v_generic; void main() { v_color = a_color; - v_color.a = v_color.a * (255.0/254.0); v_texCoords = a_texCoord0; + v_generic = a_generic; gl_Position = u_projTrans * a_position; -} +} \ No newline at end of file