Sun + dynamic lighting

This commit is contained in:
Anuken
2020-02-28 13:18:06 -05:00
parent 21bd7a75f0
commit 120d96c775
14 changed files with 360 additions and 97 deletions

View File

@@ -1,13 +1,14 @@
package mindustry.graphics;
import arc.Core;
import arc.graphics.Color;
import arc.graphics.g2d.TextureRegion;
import arc.graphics.gl.Shader;
import arc.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.graphics.gl.*;
import arc.math.*;
import arc.math.geom.*;
import arc.scene.ui.layout.Scl;
import arc.scene.ui.layout.*;
import arc.util.ArcAnnotate.*;
import arc.util.Time;
import arc.util.*;
public class Shaders{
public static Shadow shadow;
@@ -18,8 +19,9 @@ public class Shaders{
public static MenuShader menu;
public static LightShader light;
public static SurfaceShader water, tar, slag;
public static Shader planet;
public static PlanetShader planet;
public static PlanetGridShader planetGrid;
public static SunShader sun;
public static void init(){
shadow = new Shadow();
@@ -38,8 +40,63 @@ public class Shaders{
water = new SurfaceShader("water");
tar = new SurfaceShader("tar");
slag = new SurfaceShader("slag");
planet = new LoadShader("planet", "planet");
planet = new PlanetShader();
planetGrid = new PlanetGridShader();
sun = new SunShader();
}
public static class PlanetShader extends LoadShader{
public Vec3 lightDir = new Vec3(1, 1, 1).nor();
public PlanetShader(){
super("planet", "planet");
}
@Override
public void apply(){
setUniformf("u_lightdir", lightDir);
}
}
public static class SunShader extends LoadShader{
public int octaves = 5;
public float falloff = 0.5f, scale = 1f, power = 1.3f, magnitude = 0.6f, speed = 99999999999f, spread = 1.3f, seed = Mathf.random(9999f);
public Color[] colors;
public float[] colorValues;
public Vec3 center = new Vec3();
public SunShader(){
super("sun", "sun");
}
@Override
public void apply(){
setUniformi("u_octaves", octaves);
setUniformf("u_falloff", falloff);
setUniformf("u_scale", scale);
setUniformf("u_power", power);
setUniformf("u_magnitude", magnitude);
setUniformf("u_time", Time.globalTime() / speed);
setUniformf("u_seed", seed);
setUniformf("u_spread", spread);
setUniformf("u_center", center);
setUniformi("u_colornum", colors.length);
setUniform4fv("u_colors[0]", colorValues, 0, colorValues.length);
}
public void updateColors(){
colorValues = new float[colors.length*4];
for(int i = 0; i < colors.length; i ++){
colorValues[i*4] = colors[i].r;
colorValues[i*4 + 1] = colors[i].g;
colorValues[i*4 + 2] = colors[i].b;
colorValues[i*4 + 3] = colors[i].a;
}
}
}
public static class PlanetGridShader extends LoadShader{

View File

@@ -0,0 +1,61 @@
package mindustry.graphics.g3d;
import arc.graphics.*;
import arc.graphics.VertexAttributes.*;
import arc.graphics.gl.*;
import arc.math.geom.*;
import arc.util.*;
import mindustry.graphics.*;
public class GenericMesh{
protected final float[] floats = new float[3 + 3 + 1];
protected final int primitiveType;
protected final Mesh mesh;
public GenericMesh(int vertices, int primitiveType){
this.primitiveType = primitiveType;
mesh = new Mesh(true, vertices, 0,
new VertexAttribute(Usage.position, 3, Shader.positionAttribute),
new VertexAttribute(Usage.normal, 3, Shader.normalAttribute),
new VertexAttribute(Usage.colorPacked, 4, Shader.colorAttribute)
);
mesh.getVerticesBuffer().limit(mesh.getMaxVertices());
mesh.getVerticesBuffer().position(0);
}
public void render(Mat3D mat){
render(mat, Shaders.planet);
}
public void render(Mat3D mat, Shader shader){
shader.begin();
shader.setUniformMatrix4("u_projModelView", mat.val);
shader.apply();
mesh.render(shader, primitiveType);
shader.end();
}
protected Vec3 normal(Vec3 v1, Vec3 v2, Vec3 v3){
return Tmp.v32.set(v2).sub(v1).crs(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z).nor();
}
protected void verts(Vec3 a, Vec3 b, Vec3 c, Vec3 normal, Color color){
vert(a, normal, color);
vert(b, normal, color);
vert(c, normal, color);
}
protected void vert(Vec3 a, Vec3 normal, Color color){
floats[0] = a.x;
floats[1] = a.y;
floats[2] = a.z;
floats[3] = normal.x;
floats[4] = normal.y;
floats[5] = normal.z;
floats[6] = color.toFloatBits();
mesh.getVerticesBuffer().put(floats);
}
}

View File

@@ -1,4 +1,4 @@
package mindustry.graphics;
package mindustry.graphics.g3d;
import arc.math.*;
import arc.math.geom.*;
@@ -47,7 +47,7 @@ public class PlanetGrid{
}
}
public static PlanetGrid newGrid(int size){
public static PlanetGrid create(int size){
//cache grids between calls, since only ~5 different grids total are needed
if(size < cache.length && cache[size] != null){
return cache[size];
@@ -57,7 +57,7 @@ public class PlanetGrid{
if(size == 0){
result = initialGrid();
}else{
result = subdividedGrid(newGrid(size - 1));
result = subdividedGrid(create(size - 1));
}
//store grid in cache

View File

@@ -1,19 +1,13 @@
package mindustry.graphics;
package mindustry.graphics.g3d;
import arc.graphics.*;
import arc.graphics.VertexAttributes.*;
import arc.graphics.gl.*;
import arc.math.geom.*;
import arc.util.ArcAnnotate.*;
import arc.util.*;
import mindustry.graphics.PlanetGrid.*;
import mindustry.graphics.g3d.PlanetGrid.*;
public class PlanetMesh{
private static final Vec3 v1 = new Vec3(), v2 = new Vec3(), v3 = new Vec3(), v4 = new Vec3();
private float[] floats = new float[3 + 3 + 1];
public class PlanetMesh extends GenericMesh{
private Vec3 vec = new Vec3();
private Mesh mesh;
private PlanetGrid grid;
private Vec3 center = new Vec3();
@@ -27,21 +21,13 @@ public class PlanetMesh{
}
public PlanetMesh(int divisions, PlanetMesher gen, float radius, boolean lines){
super(PlanetGrid.create(divisions).tiles.length * 12 * (3 + 3 + 1), lines ? Gl.lines : Gl.triangles);
this.gen = gen;
this.radius = radius;
this.grid = PlanetGrid.newGrid(divisions);
this.grid = PlanetGrid.create(divisions);
this.lines = lines;
int vertices = grid.tiles.length * 12 * (3 + 3 + 1);
mesh = new Mesh(true, vertices, 0,
new VertexAttribute(Usage.position, 3, Shader.positionAttribute),
new VertexAttribute(Usage.normal, 3, Shader.normalAttribute),
new VertexAttribute(Usage.colorPacked, 4, Shader.colorAttribute));
mesh.getVerticesBuffer().limit(mesh.getMaxVertices());
mesh.getVerticesBuffer().position(0);
generateMesh();
}
@@ -58,23 +44,10 @@ public class PlanetMesh{
return Structs.findMin(grid.tiles, t -> t.v.dst(Tmp.v33));
}
public void render(Mat3D mat){
render(mat, Shaders.planet);
}
public void render(Mat3D mat, Shader shader){
shader.begin();
shader.setUniformMatrix4("u_projModelView", mat.val);
shader.apply();
mesh.render(shader, lines ? Gl.lines : Gl.triangles);
shader.end();
}
private void generateMesh(){
for(Ptile tile : grid.tiles){
Vec3 nor = v1.setZero();
Vec3 nor = Tmp.v31.setZero();
Corner[] c = tile.corners;
for(Corner corner : c){
@@ -119,25 +92,6 @@ public class PlanetMesh{
}
}
//unused, but functional
private void createIcosphere(){
MeshResult result = Icosphere.create(5);
for(int i = 0; i < result.indices.size; i+= 3){
v1.set(result.vertices.items, result.indices.items[i] * 3).setLength(radius).setLength(radius + elevation(v1)*intensity);
v2.set(result.vertices.items, result.indices.items[i + 1] * 3).setLength(radius).setLength(radius + elevation(v2)*intensity);
v3.set(result.vertices.items, result.indices.items[i + 2] * 3).setLength(radius).setLength(radius + elevation(v3)*intensity);
verts(v1, v3, v2,
normal(v1, v2, v3).scl(-1f),
color(v4.set(v1).add(v2).add(v3).scl(1f / 3f))
);
}
}
private Vec3 normal(Vec3 v1, Vec3 v2, Vec3 v3){
return Tmp.v32.set(v2).sub(v1).crs(v3.x - v1.x, v3.y - v1.y, v3.z - v1.z).nor();
}
private float elevation(Vec3 v){
return gen.getHeight(vec.set(v).scl(1f / radius));
}
@@ -145,23 +99,4 @@ public class PlanetMesh{
private Color color(Vec3 v){
return gen.getColor(vec.set(v).scl(1f / radius));
}
private 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 void vert(Vec3 a, Vec3 normal, Color color){
floats[0] = a.x;
floats[1] = a.y;
floats[2] = a.z;
floats[3] = normal.x;
floats[4] = normal.y;
floats[5] = normal.z;
floats[6] = color.toFloatBits();
mesh.getVerticesBuffer().put(floats);
}
}

View File

@@ -1,4 +1,4 @@
package mindustry.graphics;
package mindustry.graphics.g3d;
import arc.graphics.*;
import arc.math.geom.*;

View File

@@ -0,0 +1,24 @@
package mindustry.graphics.g3d;
import arc.graphics.*;
import arc.math.geom.*;
public class SphereMesh extends GenericMesh{
private static final Vec3 v1 = new Vec3(), v2 = new Vec3(), v3 = new Vec3(), v4 = new Vec3();
protected final float radius;
public SphereMesh(int divisions, float radius){
super(20 * (2 << (2 * divisions - 1)) * 7 * 3, Gl.triangles);
this.radius = radius;
MeshResult result = Icosphere.create(divisions);
for(int i = 0; i < result.indices.size; i+= 3){
v1.set(result.vertices.items, result.indices.items[i] * 3).setLength(radius);
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.white);
}
}
}

View File

@@ -1,7 +1,7 @@
package mindustry.maps.generators;
import arc.math.geom.*;
import mindustry.graphics.*;
import mindustry.graphics.g3d.PlanetMesher;
import mindustry.type.*;
import mindustry.world.*;

View File

@@ -9,8 +9,8 @@ import arc.util.*;
import arc.util.io.*;
import mindustry.*;
import mindustry.ctype.*;
import mindustry.graphics.*;
import mindustry.graphics.PlanetGrid.*;
import mindustry.graphics.g3d.*;
import mindustry.graphics.g3d.PlanetGrid.*;
import mindustry.maps.generators.*;
import mindustry.type.Sector.*;
@@ -35,7 +35,7 @@ public class Planet extends UnlockableContent{
this.size = 3;
grid = PlanetGrid.newGrid(size);
grid = PlanetGrid.create(size);
sectors = new Array<>(grid.tiles.length);
for(int i = 0; i < grid.tiles.length; i++){

View File

@@ -7,7 +7,7 @@ import arc.util.io.*;
import mindustry.*;
import mindustry.ctype.*;
import mindustry.game.Saves.*;
import mindustry.graphics.PlanetGrid.*;
import mindustry.graphics.g3d.PlanetGrid.*;
import mindustry.world.*;
/** A small section of a planet. */

View File

@@ -15,7 +15,8 @@ import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.graphics.PlanetGrid.*;
import mindustry.graphics.g3d.*;
import mindustry.graphics.g3d.PlanetGrid.*;
import mindustry.type.*;
import mindustry.ui.*;
@@ -35,6 +36,11 @@ public class PlanetDialog extends FloatingDialog{
private final VertexBatch3D batch = new VertexBatch3D(false, true, 0);
private final PlaneBatch3D projector = new PlaneBatch3D();
private final SphereMesh sun = new SphereMesh(3, 1.2f);
private final Bloom bloom = new Bloom(false){{
setClearColor(0, 0, 0, 0);
}};
private Planet planet = Planets.starter;
private float lastX, lastY;
private @Nullable Sector selected, hovered;
@@ -99,6 +105,23 @@ public class PlanetDialog extends FloatingDialog{
stable.pack();
stable.setPosition(0, 0, Align.center);
Shaders.sun.colors = new Color[]{
Color.valueOf("ff7a38"),
Color.valueOf("ff9638"),
Color.valueOf("ffc64c"),
Color.valueOf("ffc64c"),
Color.valueOf("ffe371"),
Color.valueOf("f4ee8e"),
};
Shaders.sun.updateColors();
Shaders.sun.scale = 1f;
Shaders.sun.speed = 1000f;
Shaders.sun.falloff = 0.3f;
Shaders.sun.octaves = 4;
Shaders.sun.spread = 1.2f;
Shaders.sun.magnitude = 0f;
shown(this::setup);
}
@@ -127,12 +150,9 @@ public class PlanetDialog extends FloatingDialog{
projector.proj(cam.combined());
batch.proj(cam.combined());
PlanetMesh outline = outline(planet.size);
Vec3 tile = outline.intersect(cam.getPickRay(Core.input.mouseX(), Core.input.mouseY()));
Shaders.planetGrid.mouse.lerp(tile == null ? Vec3.Zero : tile, 0.2f);
renderSun();
renderPlanet();
planet.mesh.render(cam.combined());
outline.render(cam.combined(), Shaders.planetGrid);
for(Sector sec : planet.sectors){
if(sec.save == null){
@@ -178,6 +198,27 @@ public class PlanetDialog extends FloatingDialog{
}
}
private void renderPlanet(){
PlanetMesh outline = outline(planet.size);
Vec3 tile = outline.intersect(cam.getPickRay(Core.input.mouseX(), Core.input.mouseY()));
Shaders.planetGrid.mouse.lerp(tile == null ? Vec3.Zero : tile, 0.2f);
Shaders.planet.lightDir.set(Shaders.sun.center).nor();
planet.mesh.render(cam.combined());
outline.render(cam.combined(), Shaders.planetGrid);
}
private void renderSun(){
bloom.capture();
Shaders.sun.center.set(-3f, 0f, 0).rotate(Vec3.Y, Time.time() / 3f);
sun.render(cam.combined(), Shaders.sun);
bloom.render();
Gl.enable(Gl.depthTest);
Gl.enable(Gl.blend);
}
private void drawBorders(Sector sector, Color base){
Color color = Tmp.c1.set(base).a(base.a + 0.3f + Mathf.absin(Time.globalTime(), 5f, 0.3f));