WIP bases with emissive lighting on Serpulo

This commit is contained in:
Anuken
2025-05-28 19:04:33 -04:00
parent 00621dbc18
commit fcb5b42d58
13 changed files with 120 additions and 18 deletions

View File

@@ -19,13 +19,17 @@ void main(){
//TODO this calculation is probably wrong //TODO this calculation is probably wrong
vec3 lightReflect = normalize(reflect(a_normal, u_lightdir)); vec3 lightReflect = normalize(reflect(a_normal, u_lightdir));
vec3 vertexEye = normalize(u_campos - (u_trans * a_position).xyz); 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); float specularFactor = dot(vertexEye, lightReflect);
if(specularFactor > 0.0){ 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))); 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; gl_Position = u_proj * u_trans * a_position;
} }

View File

@@ -1,7 +1,8 @@
package mindustry.graphics.g3d; package mindustry.graphics.g3d;
import arc.math.geom.*; import arc.math.geom.*;
import arc.util.*;
public interface GenericMesh{ public interface GenericMesh extends Disposable{
void render(PlanetParams params, Mat3D projection, Mat3D transform); void render(PlanetParams params, Mat3D projection, Mat3D transform);
} }

View File

@@ -19,4 +19,9 @@ public class MatMesh implements GenericMesh{
public void render(PlanetParams params, Mat3D projection, Mat3D transform){ public void render(PlanetParams params, Mat3D projection, Mat3D transform){
mesh.render(params, projection, tmp.set(transform).mul(mat)); mesh.render(params, projection, tmp.set(transform).mul(mat));
} }
@Override
public void dispose(){
mesh.dispose();
}
} }

View File

@@ -1,5 +1,6 @@
package mindustry.graphics.g3d; package mindustry.graphics.g3d;
import arc.*;
import arc.graphics.*; import arc.graphics.*;
import arc.math.geom.*; import arc.math.geom.*;
import mindustry.graphics.g3d.PlanetGrid.*; import mindustry.graphics.g3d.PlanetGrid.*;
@@ -7,7 +8,9 @@ import mindustry.maps.generators.*;
public class MeshBuilder{ public class MeshBuilder{
private static final Vec3 v1 = new Vec3(), v2 = new Vec3(), v3 = new Vec3(), v4 = new Vec3(); 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; private static Mesh mesh;
public static Mesh buildIcosphere(int divisions, float radius, Color color){ public static Mesh buildIcosphere(int divisions, float radius, Color color){
@@ -73,6 +76,19 @@ public class MeshBuilder{
begin(grid.tiles.length * 12); 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){ for(Ptile tile : grid.tiles){
if(mesher.skip(tile.v)){ if(mesher.skip(tile.v)){
continue; continue;
@@ -81,7 +97,7 @@ public class MeshBuilder{
Corner[] c = tile.corners; Corner[] c = tile.corners;
for(Corner corner : c){ 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); 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){ private static void begin(int count){
mesh = new Mesh(true, count, 0, mesh = new Mesh(true, count, 0,
VertexAttribute.position3, VertexAttribute.position3,
VertexAttribute.normal, !gl30 ? VertexAttribute.normal : VertexAttribute.packedNormal,
VertexAttribute.color VertexAttribute.color
); );
@@ -132,6 +148,7 @@ public class MeshBuilder{
Mesh last = mesh; Mesh last = mesh;
last.getVerticesBuffer().limit(last.getVerticesBuffer().position()); last.getVerticesBuffer().limit(last.getVerticesBuffer().position());
mesh = null; mesh = null;
return last; return last;
} }
@@ -150,11 +167,29 @@ public class MeshBuilder{
floats[1] = a.y; floats[1] = a.y;
floats[2] = a.z; floats[2] = a.z;
floats[3] = normal.x; if(gl30){
floats[4] = normal.y; floats[3] = packNormals(normal.x, normal.y, normal.z);
floats[5] = 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); 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);
}
} }

View File

@@ -15,4 +15,11 @@ public class MultiMesh implements GenericMesh{
v.render(params, projection, transform); v.render(params, projection, transform);
} }
} }
@Override
public void dispose(){
for(var mesh : meshes){
mesh.dispose();
}
}
} }

View File

@@ -240,6 +240,14 @@ public class PlanetGrid{
corners = new Corner[edgeCount]; corners = new Corner[edgeCount];
edges = new Edge[edgeCount]; edges = new Edge[edgeCount];
} }
@Override
public String toString(){
return "Ptile{" +
"id=" + id +
" " + v +
'}';
}
} }
public static class Corner{ public static class Corner{

View File

@@ -26,6 +26,8 @@ public abstract class PlanetMesh implements GenericMesh{
@Override @Override
public void render(PlanetParams params, Mat3D projection, Mat3D transform){ public void render(PlanetParams params, Mat3D projection, Mat3D transform){
if(mesh.isDisposed()) return;
preRender(params); preRender(params);
shader.bind(); shader.bind();
shader.setUniformMatrix4("u_proj", projection.val); shader.setUniformMatrix4("u_proj", projection.val);
@@ -33,4 +35,9 @@ public abstract class PlanetMesh implements GenericMesh{
shader.apply(); shader.apply();
mesh.render(shader, Gl.triangles); mesh.render(shader, Gl.triangles);
} }
@Override
public void dispose(){
mesh.dispose();
}
} }

View File

@@ -2,6 +2,7 @@ package mindustry.maps.generators;
import arc.*; import arc.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.struct.*; import arc.struct.*;
import arc.struct.ObjectIntMap.*; import arc.struct.ObjectIntMap.*;
@@ -25,6 +26,10 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe
protected @Nullable Sector sector; 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. */ /** Should generate sector bases for a planet. */
public void generateSector(Sector sector){ public void generateSector(Sector sector){

View File

@@ -47,12 +47,11 @@ public class ErekirPlanetGenerator extends PlanetGenerator{
//TODO this might be too green //TODO this might be too green
//if(block == Blocks.beryllicStone) block = Blocks.arkyicStone; //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 @Override
public float getSizeScl(){ public float getSizeScl(){
//TODO should sectors be 600, or 500 blocks?
return 2000 * 1.07f * 6f / 5f; return 2000 * 1.07f * 6f / 5f;
} }

View File

@@ -58,10 +58,10 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
); );
float water = 2f / arr[0].length; float water = 2f / arr[0].length;
Vec3 basePos = new Vec3(0.9341721, 0.0, 0.3568221);
float rawHeight(Vec3 position){ float rawHeight(Vec3 position){
position = Tmp.v33.set(position).scl(scl); 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);
return (Mathf.pow(Simplex.noise3d(seed, 7, 0.5f, 1f/3f, position.x, position.y, position.z), 2.3f) + waterOffset) / (1f + waterOffset);
} }
@Override @Override
@@ -87,10 +87,25 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
@Override @Override
public Color getColor(Vec3 position){ 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); Block block = getBlock(position);
//replace salt with sand color //replace salt with sand color
if(block == Blocks.salt) return Blocks.sand.mapColor; 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 @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){ Block getBlock(Vec3 position){
//float metalDst = position.dst(basePos);
float height = rawHeight(position); float height = rawHeight(position);
Tmp.v31.set(position); Tmp.v31.set(position);
position = Tmp.v33.set(position).scl(scl); position = Tmp.v33.set(position).scl(scl);
float rad = scl; float rad = scl;
float temp = Mathf.clamp(Math.abs(position.y * 2f) / (rad)); 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); 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){ if(tar > 0.5f){
return tars.get(res, res); return tars.get(res, res);
}else{ }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; return res;
} }
} }

View File

@@ -32,7 +32,7 @@ public class TantrosPlanetGenerator extends PlanetGenerator{
@Override @Override
public Color getColor(Vec3 position){ public Color getColor(Vec3 position){
float depth = Simplex.noise3d(seed, 2, 0.56, 1.7f, position.x, position.y, position.z) / 2f; 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 @Override

View File

@@ -43,6 +43,8 @@ public class Planet extends UnlockableContent{
public @Nullable GenericMesh cloudMesh; public @Nullable GenericMesh cloudMesh;
/** Mesh used for rendering planet grid outlines. Null on server or if {@link #grid} is null. */ /** Mesh used for rendering planet grid outlines. Null on server or if {@link #grid} is null. */
public @Nullable Mesh gridMesh; 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. */ /** Position in global coordinates. Will be 0,0,0 until the Universe updates it. */
public Vec3 position = new Vec3(); public Vec3 position = new Vec3();
/** Grid used for the sectors on the planet. Null if this planet can't be landed on. */ /** 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()); return mat.setToTranslation(position).rotate(Vec3.Y, getRotation());
} }
/** Regenerates the planet mesh. For debugging only. */ /** Regenerates the planet mesh. */
public void reloadMesh(){ public void reloadMesh(){
if(headless) return;
if(mesh != null){
mesh.dispose();
}
mesh = meshLoader.get(); mesh = meshLoader.get();
} }

View File

@@ -26,4 +26,4 @@ org.gradle.caching=true
org.gradle.internal.http.socketTimeout=100000 org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000 org.gradle.internal.http.connectionTimeout=100000
android.enableR8.fullMode=false android.enableR8.fullMode=false
archash=67b872ff4d archash=f125488119