Emissive planet system upgrades / Indexed vertices for planets

This commit is contained in:
Anuken
2025-05-28 21:21:21 -04:00
parent fcb5b42d58
commit 43fb2e7cdc
15 changed files with 193 additions and 82 deletions

View File

@@ -32,7 +32,7 @@ public class LoadRenderer implements Disposable{
private float testprogress = 0f;
private StringBuilder assetText = new StringBuilder();
private Bar[] bars;
private Mesh mesh = MeshBuilder.buildHex(colorRed, 2, true, 1f);
private Mesh mesh = MeshBuilder.buildLineHex(colorRed, 2);
private Camera3D cam = new Camera3D();
private int lastLength = -1;
private FxProcessor fx;

View File

@@ -109,6 +109,7 @@ public class Shaders{
public Color ambientColor = Color.white.cpy();
public Vec3 camDir = new Vec3();
public Vec3 camPos = new Vec3();
public boolean emissive;
public Planet planet;
public PlanetShader(){
@@ -123,6 +124,7 @@ public class Shaders{
setUniformf("u_ambientColor", ambientColor.r, ambientColor.g, ambientColor.b);
setUniformf("u_camdir", camDir);
setUniformf("u_campos", renderer.planets.cam.position);
setUniformf("u_emissive", emissive ? 1f : 0f);
}
}

View File

@@ -8,11 +8,11 @@ import mindustry.type.*;
public class HexMesh extends PlanetMesh{
public HexMesh(Planet planet, int divisions){
super(planet, MeshBuilder.buildHex(planet.generator, divisions, false, planet.radius, 0.2f), Shaders.planet);
super(planet, MeshBuilder.buildHex(planet.generator, divisions, planet.radius, 0.2f), Shaders.planet);
}
public HexMesh(Planet planet, HexMesher mesher, int divisions, Shader shader){
super(planet, MeshBuilder.buildHex(mesher, divisions, false, planet.radius, 0.2f), shader);
super(planet, MeshBuilder.buildHex(mesher, divisions, planet.radius, 0.2f), shader);
}
public HexMesh(){
@@ -21,6 +21,7 @@ public class HexMesh extends PlanetMesh{
@Override
public void preRender(PlanetParams params){
Shaders.planet.planet = planet;
Shaders.planet.emissive = planet.generator != null && planet.generator.hasEmissive();
Shaders.planet.lightDir.set(planet.solarSystem.position).sub(planet.position).rotate(Vec3.Y, planet.getRotation()).nor();
Shaders.planet.ambientColor.set(planet.solarSystem.lightColor);
}

View File

@@ -5,8 +5,18 @@ import arc.math.geom.*;
/** Defines color and height for a planet mesh. */
public interface HexMesher{
float getHeight(Vec3 position);
Color getColor(Vec3 position);
default Color getEmissiveColor(Vec3 position){
return Color.clear;
}
default boolean hasEmissive(){
return false;
}
default boolean skip(Vec3 position){
return false;
}

View File

@@ -29,7 +29,7 @@ public class HexSkyMesh extends PlanetMesh{
public boolean skip(Vec3 position){
return Simplex.noise3d(7 + seed, octaves, persistence, scl, position.x, position.y * 3f, position.z) >= thresh;
}
}, divisions, false, planet.radius, radius), Shaders.clouds);
}, divisions, planet.radius, radius), Shaders.clouds);
this.speed = speed;
}

View File

@@ -3,18 +3,23 @@ package mindustry.graphics.g3d;
import arc.*;
import arc.graphics.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.graphics.g3d.PlanetGrid.*;
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 boolean gl30 = Core.gl30 != null;
private static final float[] floats = new float[3 + (gl30 ? 1 : 3) + 1];
private static final float[] floats = new float[3 + (gl30 ? 1 : 3) + 1], emissiveFloats = new float[floats.length + 1];
private static final short[] shorts = new short[3];
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){
begin(20 * (2 << (2 * divisions - 1)) * 3);
begin(20 * (2 << (2 * divisions - 1)) * 3, 0, false);
float col = color.toFloatBits();
MeshResult result = Icosphere.create(divisions);
for(int i = 0; i < result.indices.size; i+= 3){
@@ -22,7 +27,7 @@ public class MeshBuilder{
v2.set(result.vertices.items, result.indices.items[i + 1] * 3).setLength(radius);
v3.set(result.vertices.items, result.indices.items[i + 2] * 3).setLength(radius);
verts(v1, v3, v2, normal(v1, v2, v3).scl(-1f), color);
verts(v1, v3, v2, normal(v1, v2, v3).scl(-1f), col, 0f);
}
return end();
@@ -38,22 +43,48 @@ public class MeshBuilder{
total += tile.corners.length * 2;
}
begin(total);
float col = color.toFloatBits();
begin(total, 0, false);
for(Ptile tile : grid.tiles){
Corner[] c = tile.corners;
for(int i = 0; i < c.length; i++){
Vec3 a = v1.set(c[i].v).scl(scale);
Vec3 b = v2.set(c[(i + 1) % c.length].v).scl(scale);
vert(a, Vec3.Z, color);
vert(b, Vec3.Z, color);
vert(a, Vec3.Z, col, 0f);
vert(b, Vec3.Z, col, 0f);
}
}
return end();
}
public static Mesh buildHex(Color color, int divisions, boolean lines, float radius){
public static Mesh buildLineHex(Color color, int divisions){
PlanetGrid grid = PlanetGrid.create(divisions);
begin(grid.tiles.length * 12, 0, false);
Vec3 nor = v4.set(1f, 1f, 1f);
float col = color.toFloatBits();
for(Ptile tile : grid.tiles){
Corner[] c = tile.corners;
for(int i = 0; i < c.length; i++){
Vec3 v1 = c[i].v;
Vec3 v2 = c[(i + 1) % c.length].v;
vert(v1, nor, col, 0f);
vert(v2, nor, col, 0f);
}
}
return end();
}
public static Mesh buildHex(Color color, int divisions, float radius){
return buildHex(new HexMesher(){
@Override
public float getHeight(Vec3 position){
@@ -64,17 +95,25 @@ public class MeshBuilder{
public Color getColor(Vec3 position){
return color;
}
}, divisions, lines, radius, 0);
}, divisions, radius, 0);
}
public static Mesh buildHex(HexMesher mesher, int divisions, boolean lines, float radius, float intensity){
public static Mesh buildHex(HexMesher mesher, int divisions, float radius, float intensity){
PlanetGrid grid = PlanetGrid.create(divisions);
if(mesher instanceof PlanetGenerator generator){
generator.seed = generator.baseSeed;
}
begin(grid.tiles.length * 12);
boolean emit = mesher.hasEmissive();
boolean indexed = grid.tiles.length * 6 < 65535;
if(indexed){
begin(grid.tiles.length * 6, grid.tiles.length * 4 * 3, emit);
}else{
begin(grid.tiles.length * 12, 0, emit);
}
float[] heights;
@@ -89,6 +128,8 @@ public class MeshBuilder{
heights[i] = mesher.getHeight(grid.corners[i].v);
}
int position = 0;
for(Ptile tile : grid.tiles){
if(mesher.skip(tile.v)){
continue;
@@ -101,25 +142,30 @@ public class MeshBuilder{
}
Vec3 nor = normal(c[0].v, c[2].v, c[4].v);
Color color = mesher.getColor(v2.set(tile.v));
float color = mesher.getColor(tile.v).toFloatBits();
float emissive = emit ? mesher.getEmissiveColor(tile.v).toFloatBits() : 0f;
if(lines){
nor.set(1f, 1f, 1f);
for(int i = 0; i < c.length; i++){
Vec3 v1 = c[i].v;
Vec3 v2 = c[(i + 1) % c.length].v;
vert(v1, nor, color);
vert(v2, nor, color);
if(indexed){
for(var corner : c){
vert(corner.v, nor, color, emissive);
}
indices(position, position + 1, position + 2);
indices(position, position + 2, position + 3);
indices(position, position + 3, position + 4);
if(c.length > 5){
indices(position, position + 4, position + 5);
}
position += c.length;
}else{
verts(c[0].v, c[1].v, c[2].v, nor, color);
verts(c[0].v, c[2].v, c[3].v, nor, color);
verts(c[0].v, c[3].v, c[4].v, nor, color);
verts(c[0].v, c[1].v, c[2].v, nor, color, emissive);
verts(c[0].v, c[2].v, c[3].v, nor, color, emissive);
verts(c[0].v, c[3].v, c[4].v, nor, color, emissive);
if(c.length > 5){
verts(c[0].v, c[4].v, c[5].v, nor, color);
verts(c[0].v, c[4].v, c[5].v, nor, color, emissive);
}
}
@@ -127,28 +173,49 @@ public class MeshBuilder{
for(Corner corner : c){
corner.v.nor();
}
}
return end();
}
private static void begin(int count){
mesh = new Mesh(true, count, 0,
private static void begin(int vertices, int indices, boolean emissive){
Seq<VertexAttribute> attributes = Seq.with(
VertexAttribute.position3,
!gl30 ? VertexAttribute.normal : VertexAttribute.packedNormal,
//only GL30 supports GL_INT_2_10_10_10_REV
gl30 ? VertexAttribute.packedNormal : VertexAttribute.normal,
VertexAttribute.color
);
if(emissive){
attributes.add(new VertexAttribute(4, GL20.GL_UNSIGNED_BYTE, true, "a_emissive"));
}
mesh = new Mesh(true, vertices, indices, attributes.toArray(VertexAttribute.class));
mesh.getVerticesBuffer().limit(mesh.getVerticesBuffer().capacity());
mesh.getVerticesBuffer().position(0);
if(indices > 0){
mesh.getIndicesBuffer().limit(mesh.getIndicesBuffer().capacity());
mesh.getIndicesBuffer().position(0);
}
}
static int totalBytes;
private static Mesh end(){
Mesh last = mesh;
last.getVerticesBuffer().limit(last.getVerticesBuffer().position());
if(last.getNumIndices() > 0){
last.getIndicesBuffer().limit(last.getIndicesBuffer().position());
}
mesh = null;
totalBytes += last.getVerticesBuffer().capacity() * 4;
totalBytes += last.getIndicesBuffer().capacity() * 2;
Log.info("total memory used: @ mb", totalBytes / 1000f / 1000f);
return last;
}
@@ -156,13 +223,23 @@ public class MeshBuilder{
return v4.set(v2).sub(v1).crs(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z).nor();
}
private static void verts(Vec3 a, Vec3 b, Vec3 c, Vec3 normal, Color color){
vert(a, normal, color);
vert(b, normal, color);
vert(c, normal, color);
private static void indices(int a, int b, int c){
shorts[0] = (short)a;
shorts[1] = (short)b;
shorts[2] = (short)c;
mesh.getIndicesBuffer().put(shorts);
}
private static void vert(Vec3 a, Vec3 normal, Color color){
private static void verts(Vec3 a, Vec3 b, Vec3 c, Vec3 normal, float color, float emissive){
vert(a, normal, color, emissive);
vert(b, normal, color, emissive);
vert(c, normal, color, emissive);
}
private static void vert(Vec3 a, Vec3 normal, float color, float emissive){
boolean emit = mesh.getVertexSize() == emissiveFloats.length*4;
float[] floats = emit ? emissiveFloats : MeshBuilder.floats;
floats[0] = a.x;
floats[1] = a.y;
floats[2] = a.z;
@@ -170,13 +247,15 @@ public class MeshBuilder{
if(gl30){
floats[3] = packNormals(normal.x, normal.y, normal.z);
floats[4] = color.toFloatBits();
floats[4] = color;
if(emit) floats[5] = emissive;
}else{
floats[3] = normal.x;
floats[4] = normal.x;
floats[5] = normal.x;
floats[6] = color.toFloatBits();
floats[6] = color;
if(emit) floats[7] = emissive;
}
mesh.getVerticesBuffer().put(floats);

View File

@@ -21,7 +21,7 @@ public class NoiseMesh extends HexMesh{
public Color getColor(Vec3 position){
return color;
}
}, divisions, false, radius, 0.2f);
}, divisions, radius, 0.2f);
}
/** Two-color variant. */
@@ -38,6 +38,6 @@ public class NoiseMesh extends HexMesh{
public Color getColor(Vec3 position){
return Simplex.noise3d(8 + seed, coct, cper, cscl, 5f + position.x, 5f + position.y, 5f + position.z) > cthresh ? color2 : color1;
}
}, divisions, false, radius, 0.2f);
}, divisions, radius, 0.2f);
}
}

View File

@@ -31,7 +31,7 @@ public class PlanetRenderer implements Disposable{
setThreshold(0.8f);
blurPasses = 6;
}};
public final Mesh atmosphere = MeshBuilder.buildHex(Color.white, 2, false, 1.5f);
public final Mesh atmosphere = MeshBuilder.buildHex(Color.white, 2, 1.5f);
//seed: 8kmfuix03fw
public final CubemapMesh skybox = new CubemapMesh(new Cubemap("cubemaps/stars/"));