From fcb5b42d58e8a7c6f95bf277e3585887eb5c7bcb Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 28 May 2025 19:04:33 -0400 Subject: [PATCH] WIP bases with emissive lighting on Serpulo --- core/assets/shaders/planet.vert | 8 ++- .../mindustry/graphics/g3d/GenericMesh.java | 3 +- core/src/mindustry/graphics/g3d/MatMesh.java | 5 ++ .../mindustry/graphics/g3d/MeshBuilder.java | 49 ++++++++++++++++--- .../src/mindustry/graphics/g3d/MultiMesh.java | 7 +++ .../mindustry/graphics/g3d/PlanetGrid.java | 8 +++ .../mindustry/graphics/g3d/PlanetMesh.java | 7 +++ .../maps/generators/PlanetGenerator.java | 5 ++ .../maps/planet/ErekirPlanetGenerator.java | 3 +- .../maps/planet/SerpuloPlanetGenerator.java | 30 ++++++++++-- .../maps/planet/TantrosPlanetGenerator.java | 2 +- core/src/mindustry/type/Planet.java | 9 +++- gradle.properties | 2 +- 13 files changed, 120 insertions(+), 18 deletions(-) diff --git a/core/assets/shaders/planet.vert b/core/assets/shaders/planet.vert index 7c73fb8aa5..8d592aa919 100755 --- a/core/assets/shaders/planet.vert +++ b/core/assets/shaders/planet.vert @@ -19,13 +19,17 @@ void main(){ //TODO this calculation is probably wrong vec3 lightReflect = normalize(reflect(a_normal, u_lightdir)); vec3 vertexEye = normalize(u_campos - (u_trans * a_position).xyz); + + float albedo = a_color.a > 0.5 ? 0.0 : min(a_color.a * 2.0, 1.0); + float emissive = a_color.a < 0.5 ? 0.0 : 1.0 - (a_color.a - 0.5) * 2.0; + float specularFactor = dot(vertexEye, lightReflect); if(specularFactor > 0.0){ - specular = vec3(1.0 * pow(specularFactor, 40.0)) * (1.0-a_color.a); + specular = vec3(1.0 * pow(specularFactor, 40.0)) * albedo; } vec3 norc = (u_ambientColor + specular) * (diffuse + vec3(clamp((dot(a_normal, u_lightdir) + 1.0) / 2.0, 0.0, 1.0))); - v_col = vec4(a_color.rgb, 1.0) * vec4(norc, 1.0); + v_col = vec4(a_color.rgb, 1.0) * vec4(mix(norc, vec3(1.0), emissive), 1.0); gl_Position = u_proj * u_trans * a_position; } diff --git a/core/src/mindustry/graphics/g3d/GenericMesh.java b/core/src/mindustry/graphics/g3d/GenericMesh.java index d4198f5d9a..c6e57f4a10 100644 --- a/core/src/mindustry/graphics/g3d/GenericMesh.java +++ b/core/src/mindustry/graphics/g3d/GenericMesh.java @@ -1,7 +1,8 @@ package mindustry.graphics.g3d; import arc.math.geom.*; +import arc.util.*; -public interface GenericMesh{ +public interface GenericMesh extends Disposable{ void render(PlanetParams params, Mat3D projection, Mat3D transform); } diff --git a/core/src/mindustry/graphics/g3d/MatMesh.java b/core/src/mindustry/graphics/g3d/MatMesh.java index 5fd064dfda..2595b15ecb 100644 --- a/core/src/mindustry/graphics/g3d/MatMesh.java +++ b/core/src/mindustry/graphics/g3d/MatMesh.java @@ -19,4 +19,9 @@ public class MatMesh implements GenericMesh{ public void render(PlanetParams params, Mat3D projection, Mat3D transform){ mesh.render(params, projection, tmp.set(transform).mul(mat)); } + + @Override + public void dispose(){ + mesh.dispose(); + } } diff --git a/core/src/mindustry/graphics/g3d/MeshBuilder.java b/core/src/mindustry/graphics/g3d/MeshBuilder.java index 6bc0688552..c0b8b0f2f4 100644 --- a/core/src/mindustry/graphics/g3d/MeshBuilder.java +++ b/core/src/mindustry/graphics/g3d/MeshBuilder.java @@ -1,5 +1,6 @@ package mindustry.graphics.g3d; +import arc.*; import arc.graphics.*; import arc.math.geom.*; import mindustry.graphics.g3d.PlanetGrid.*; @@ -7,7 +8,9 @@ import mindustry.maps.generators.*; public class MeshBuilder{ private static final Vec3 v1 = new Vec3(), v2 = new Vec3(), v3 = new Vec3(), v4 = new Vec3(); - private static final float[] floats = new float[3 + 3 + 1]; + private static final boolean gl30 = Core.gl30 != null; + private static final float[] floats = new float[3 + (gl30 ? 1 : 3) + 1]; + private static float[] tmpHeights = new float[14580]; //highest amount of corners in vanilla private static Mesh mesh; public static Mesh buildIcosphere(int divisions, float radius, Color color){ @@ -73,6 +76,19 @@ public class MeshBuilder{ begin(grid.tiles.length * 12); + float[] heights; + + if(tmpHeights == null || tmpHeights.length < grid.corners.length){ + heights = tmpHeights = new float[grid.corners.length]; + }else{ + heights = tmpHeights; + } + + //cache heights in an array to prevent redundant calls to getHeight + for(int i = 0; i < grid.corners.length; i++){ + heights[i] = mesher.getHeight(grid.corners[i].v); + } + for(Ptile tile : grid.tiles){ if(mesher.skip(tile.v)){ continue; @@ -81,7 +97,7 @@ public class MeshBuilder{ Corner[] c = tile.corners; for(Corner corner : c){ - corner.v.setLength((1f + mesher.getHeight(v2.set(corner.v)) * intensity) * radius); + corner.v.scl((1f + heights[corner.id] * intensity) * radius); } Vec3 nor = normal(c[0].v, c[2].v, c[4].v); @@ -120,7 +136,7 @@ public class MeshBuilder{ private static void begin(int count){ mesh = new Mesh(true, count, 0, VertexAttribute.position3, - VertexAttribute.normal, + !gl30 ? VertexAttribute.normal : VertexAttribute.packedNormal, VertexAttribute.color ); @@ -132,6 +148,7 @@ public class MeshBuilder{ Mesh last = mesh; last.getVerticesBuffer().limit(last.getVerticesBuffer().position()); mesh = null; + return last; } @@ -150,11 +167,29 @@ public class MeshBuilder{ floats[1] = a.y; floats[2] = a.z; - floats[3] = normal.x; - floats[4] = normal.y; - floats[5] = normal.z; + if(gl30){ + floats[3] = packNormals(normal.x, normal.y, normal.z); + + floats[4] = color.toFloatBits(); + }else{ + floats[3] = normal.x; + floats[4] = normal.x; + floats[5] = normal.x; + + floats[6] = color.toFloatBits(); + } - floats[6] = color.toFloatBits(); mesh.getVerticesBuffer().put(floats); } + + private static float packNormals(float x, float y, float z){ + int xs = x < 0 ? 1 : 0; + int ys = y < 0 ? 1 : 0; + int zs = z < 0 ? 1 : 0; + int vi = + zs << 29 | ((int)(z * 511 + (zs << 9)) & 511) << 20 | + ys << 19 | ((int)(y * 511 + (ys << 9)) & 511) << 10 | + xs << 9 | ((int)(x * 511 + (xs << 9)) & 511); + return Float.intBitsToFloat(vi); + } } diff --git a/core/src/mindustry/graphics/g3d/MultiMesh.java b/core/src/mindustry/graphics/g3d/MultiMesh.java index 2512a5f172..7178d8a223 100644 --- a/core/src/mindustry/graphics/g3d/MultiMesh.java +++ b/core/src/mindustry/graphics/g3d/MultiMesh.java @@ -15,4 +15,11 @@ public class MultiMesh implements GenericMesh{ v.render(params, projection, transform); } } + + @Override + public void dispose(){ + for(var mesh : meshes){ + mesh.dispose(); + } + } } diff --git a/core/src/mindustry/graphics/g3d/PlanetGrid.java b/core/src/mindustry/graphics/g3d/PlanetGrid.java index 993ca34c25..7e8950d49e 100644 --- a/core/src/mindustry/graphics/g3d/PlanetGrid.java +++ b/core/src/mindustry/graphics/g3d/PlanetGrid.java @@ -240,6 +240,14 @@ public class PlanetGrid{ corners = new Corner[edgeCount]; edges = new Edge[edgeCount]; } + + @Override + public String toString(){ + return "Ptile{" + + "id=" + id + + " " + v + + '}'; + } } public static class Corner{ diff --git a/core/src/mindustry/graphics/g3d/PlanetMesh.java b/core/src/mindustry/graphics/g3d/PlanetMesh.java index 321cd85e31..9e3f9fb359 100644 --- a/core/src/mindustry/graphics/g3d/PlanetMesh.java +++ b/core/src/mindustry/graphics/g3d/PlanetMesh.java @@ -26,6 +26,8 @@ public abstract class PlanetMesh implements GenericMesh{ @Override public void render(PlanetParams params, Mat3D projection, Mat3D transform){ + if(mesh.isDisposed()) return; + preRender(params); shader.bind(); shader.setUniformMatrix4("u_proj", projection.val); @@ -33,4 +35,9 @@ public abstract class PlanetMesh implements GenericMesh{ shader.apply(); mesh.render(shader, Gl.triangles); } + + @Override + public void dispose(){ + mesh.dispose(); + } } diff --git a/core/src/mindustry/maps/generators/PlanetGenerator.java b/core/src/mindustry/maps/generators/PlanetGenerator.java index 5fd3b19931..7e561f9b31 100644 --- a/core/src/mindustry/maps/generators/PlanetGenerator.java +++ b/core/src/mindustry/maps/generators/PlanetGenerator.java @@ -2,6 +2,7 @@ package mindustry.maps.generators; import arc.*; import arc.graphics.g2d.*; +import arc.math.*; import arc.math.geom.*; import arc.struct.*; import arc.struct.ObjectIntMap.*; @@ -25,6 +26,10 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe protected @Nullable Sector sector; + public static float packAlpha(float albedo, float emissive){ + return emissive > 0 ? 1f + 1f/255f - 0.5f * Mathf.clamp(emissive) : Mathf.clamp(albedo) * 0.5f; + } + /** Should generate sector bases for a planet. */ public void generateSector(Sector sector){ diff --git a/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java b/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java index 94b4dd8992..f104f6bc53 100644 --- a/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java +++ b/core/src/mindustry/maps/planet/ErekirPlanetGenerator.java @@ -47,12 +47,11 @@ public class ErekirPlanetGenerator extends PlanetGenerator{ //TODO this might be too green //if(block == Blocks.beryllicStone) block = Blocks.arkyicStone; - return Tmp.c1.set(block.mapColor).a(1f - block.albedo); + return Tmp.c1.set(block.mapColor).a(packAlpha(block.albedo, 0f)); } @Override public float getSizeScl(){ - //TODO should sectors be 600, or 500 blocks? return 2000 * 1.07f * 6f / 5f; } diff --git a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java index ccba966da1..a785bcf9d0 100644 --- a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java +++ b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java @@ -58,10 +58,10 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ ); float water = 2f / arr[0].length; + Vec3 basePos = new Vec3(0.9341721, 0.0, 0.3568221); float rawHeight(Vec3 position){ - position = Tmp.v33.set(position).scl(scl); - return (Mathf.pow(Simplex.noise3d(seed, 7, 0.5f, 1f/3f, position.x, position.y, position.z), 2.3f) + waterOffset) / (1f + waterOffset); + return (Mathf.pow(Simplex.noise3d(seed, 7, 0.5f, 1f/3f, position.x * scl, position.y * scl, position.z * scl), 2.3f) + waterOffset) / (1f + waterOffset); } @Override @@ -87,10 +87,25 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ @Override public Color getColor(Vec3 position){ + float dst = 999f; + for(Sector sector : Planets.serpulo.sectors){ + if(sector.hasEnemyBase() && !sector.isCaptured()){ + dst = Math.min(dst, position.dst(sector.tile.v)); + } + } + + if(position.dst(basePos) < 0.55f && dst*metalDstScl + Simplex.noise3d(seed, 3, 0.4, 5.5f, position.x, position.y + 200f, position.z)*0.08f < 0.06f){ + return Tmp.c1.set(Team.crux.color).lerp(Team.sharded.color, 0.4f*Simplex.noise3d(seed, 1, 1, 9f, position.x, position.y + 999f, position.z)).a(packAlpha(0f, 1f)); + } + + //if(dst*metalDstScl + Simplex.noise3d(seed, 3, 0.4, 4f, position.x, position.y + 200f, position.z)*0.14f < 0.09f){ + // return Tmp.c1.set(Team.crux.color).lerp(Team.sharded.color, 0.4f*Simplex.noise3d(seed, 1, 1, 9f, position.x, position.y + 999f, position.z)).a(packAlpha(0f, 1f)); + //} + Block block = getBlock(position); //replace salt with sand color if(block == Blocks.salt) return Blocks.sand.mapColor; - return Tmp.c1.set(block.mapColor).a(1f - block.albedo); + return Tmp.c1.set(block.mapColor).a(packAlpha(block.albedo, 0f)); } @Override @@ -103,10 +118,14 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ } } + public static double metalMag = 0.11, metalScl = 1, metalDstScl = 0.25, metalThresh = 0.1; + Block getBlock(Vec3 position){ + //float metalDst = position.dst(basePos); float height = rawHeight(position); Tmp.v31.set(position); position = Tmp.v33.set(position).scl(scl); + float rad = scl; float temp = Mathf.clamp(Math.abs(position.y * 2f) / (rad)); float tnoise = Simplex.noise3d(seed, 7, 0.56, 1f/3f, position.x, position.y + 999f, position.z); @@ -120,6 +139,11 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ if(tar > 0.5f){ return tars.get(res, res); }else{ + //TODO: add this later once presets are defined for this side + /* + if(metalDst*metalDstScl + Simplex.noise3d(seed, 3, 0.4, metalScl, position.x, position.y + 99f, position.z)*metalMag < metalThresh){ + return Blocks.metalFloor; + }*/ return res; } } diff --git a/core/src/mindustry/maps/planet/TantrosPlanetGenerator.java b/core/src/mindustry/maps/planet/TantrosPlanetGenerator.java index 8925536a83..fddb467bdf 100644 --- a/core/src/mindustry/maps/planet/TantrosPlanetGenerator.java +++ b/core/src/mindustry/maps/planet/TantrosPlanetGenerator.java @@ -32,7 +32,7 @@ public class TantrosPlanetGenerator extends PlanetGenerator{ @Override public Color getColor(Vec3 position){ float depth = Simplex.noise3d(seed, 2, 0.56, 1.7f, position.x, position.y, position.z) / 2f; - return c1.write(out).lerp(c2, Mathf.clamp(Mathf.round(depth, 0.15f))).a(0.2f); + return c1.write(out).lerp(c2, Mathf.clamp(Mathf.round(depth, 0.15f))).a(packAlpha(0.2f, 0f)); } @Override diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index 06ee987469..1ccbe0e5bb 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -43,6 +43,8 @@ public class Planet extends UnlockableContent{ public @Nullable GenericMesh cloudMesh; /** Mesh used for rendering planet grid outlines. Null on server or if {@link #grid} is null. */ public @Nullable Mesh gridMesh; + /** If true, this planet's mesh should be reloaded when it is next shown. */ + public boolean requiresMeshReload; /** Position in global coordinates. Will be 0,0,0 until the Universe updates it. */ public Vec3 position = new Vec3(); /** Grid used for the sectors on the planet. Null if this planet can't be landed on. */ @@ -348,8 +350,13 @@ public class Planet extends UnlockableContent{ return mat.setToTranslation(position).rotate(Vec3.Y, getRotation()); } - /** Regenerates the planet mesh. For debugging only. */ + /** Regenerates the planet mesh. */ public void reloadMesh(){ + if(headless) return; + + if(mesh != null){ + mesh.dispose(); + } mesh = meshLoader.get(); } diff --git a/gradle.properties b/gradle.properties index fcb7e71f43..0ba2e1b4a2 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=67b872ff4d +archash=f125488119