I waste several hours
This commit is contained in:
173
core/src/mindustry/graphics/FogRenderer.java
Normal file
173
core/src/mindustry/graphics/FogRenderer.java
Normal file
@@ -0,0 +1,173 @@
|
||||
package mindustry.graphics;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.Texture.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.graphics.gl.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.io.*;
|
||||
import mindustry.io.SaveFileReader.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
/** Highly experimental fog-of-war renderer. */
|
||||
public class FogRenderer implements CustomChunk{
|
||||
private static final float fogSpeed = 1f;
|
||||
private FrameBuffer buffer = new FrameBuffer();
|
||||
private Seq<Building> events = new Seq<>();
|
||||
private boolean read = false;
|
||||
private Rect rect = new Rect();
|
||||
|
||||
public FogRenderer(){
|
||||
SaveVersion.addCustomChunk("fog", this);
|
||||
|
||||
Events.on(WorldLoadEvent.class, event -> {
|
||||
if(state.rules.fog){
|
||||
buffer.resize(world.width(), world.height());
|
||||
|
||||
events.clear();
|
||||
Groups.build.copy(events);
|
||||
|
||||
//clear
|
||||
if(!read){
|
||||
buffer.begin(Color.black);
|
||||
buffer.end();
|
||||
}
|
||||
|
||||
read = false;
|
||||
}
|
||||
});
|
||||
|
||||
//draw fog when tile is placed.
|
||||
Events.on(TileChangeEvent.class, event -> {
|
||||
if(state.rules.fog && event.tile.build != null && event.tile.isCenter()){
|
||||
events.add(event.tile.build);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Texture getTexture(){
|
||||
return buffer.getTexture();
|
||||
}
|
||||
|
||||
public void drawFog(){
|
||||
//resize if world size changes
|
||||
buffer.resize(world.width(), world.height());
|
||||
|
||||
//set projection to whole map
|
||||
Draw.proj(0, 0, buffer.getWidth() * tilesize, buffer.getHeight() * tilesize);
|
||||
buffer.begin();
|
||||
Gl.blendEquationSeparate(Gl.max, Gl.max);
|
||||
ScissorStack.push(rect.set(1, 1, buffer.getWidth() - 2, buffer.getHeight() - 2));
|
||||
|
||||
Draw.color(Color.white);
|
||||
|
||||
for(var build : events){
|
||||
if(build.team == player.team()){
|
||||
Fill.circle(build.x, build.y, 40f);
|
||||
}
|
||||
}
|
||||
events.clear();
|
||||
|
||||
Draw.alpha(fogSpeed * Math.max(Time.delta, 1f));
|
||||
|
||||
//TODO slow and terrible
|
||||
Groups.unit.each(u -> {
|
||||
if(u.team == player.team()){
|
||||
Fill.circle(u.x, u.y, u.type.lightRadius);
|
||||
}
|
||||
});
|
||||
|
||||
buffer.end();
|
||||
buffer.getTexture().setFilter(TextureFilter.linear);
|
||||
Gl.blendEquationSeparate(Gl.funcAdd, Gl.funcAdd);
|
||||
ScissorStack.pop();
|
||||
|
||||
Draw.proj(Core.camera);
|
||||
|
||||
Draw.shader(Shaders.fog);
|
||||
Draw.fbo(buffer.getTexture(), world.width(), world.height(), tilesize);
|
||||
Draw.shader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
ByteBuffer bytes = Buffers.newUnsafeByteBuffer(buffer.getWidth() * buffer.getHeight() * 4);
|
||||
try{
|
||||
bytes.position(0);
|
||||
buffer.begin();
|
||||
Gl.readPixels(0, 0, buffer.getWidth(), buffer.getHeight(), Gl.rgba, Gl.unsignedByte, bytes);
|
||||
buffer.end();
|
||||
bytes.position(0);
|
||||
stream.writeShort(buffer.getWidth());
|
||||
stream.writeShort(buffer.getHeight());
|
||||
|
||||
//TODO flip?
|
||||
|
||||
int pos = 0, size = bytes.capacity() / 4;
|
||||
while(pos < size){
|
||||
int consecutives = 0;
|
||||
boolean cur = bytes.get(pos * 4) != 0;
|
||||
while(consecutives < 127 && pos < size){
|
||||
boolean next = bytes.get(pos * 4) != 0;
|
||||
if(cur != next){
|
||||
break;
|
||||
}
|
||||
|
||||
consecutives ++;
|
||||
pos ++;
|
||||
}
|
||||
int mask = (cur ? 0b1000_0000 : 0);
|
||||
stream.write(mask | (consecutives));
|
||||
}
|
||||
}finally{
|
||||
Buffers.disposeUnsafeByteBuffer(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream) throws IOException{
|
||||
short w = stream.readShort(), h = stream.readShort();
|
||||
int pos = 0;
|
||||
int len = w * h;
|
||||
buffer.resize(w, h);
|
||||
buffer.begin(Color.black);
|
||||
Draw.proj(0, 0, buffer.getWidth(), buffer.getHeight());
|
||||
Draw.color();
|
||||
|
||||
while(pos < len){
|
||||
int data = stream.readByte() & 0xff;
|
||||
boolean sign = (data & 0b1000_0000) != 0;
|
||||
int consec = data & 0b0111_1111;
|
||||
|
||||
if(sign){
|
||||
for(int i = 0; i < consec; i++){
|
||||
int x = pos % w, y = pos / w;
|
||||
//TODO this is slow
|
||||
Fill.rect(x + 0.5f, y + 0.5f, 1f, 1f);
|
||||
|
||||
pos ++;
|
||||
}
|
||||
}else{
|
||||
pos += consec;
|
||||
}
|
||||
}
|
||||
|
||||
buffer.end();
|
||||
Draw.proj(Core.camera);
|
||||
read = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldWrite(){
|
||||
return state.rules.fog && buffer.getTexture() != null && buffer.getWidth() > 0;
|
||||
}
|
||||
}
|
||||
@@ -92,6 +92,9 @@ public class Layer{
|
||||
//names of players in the game
|
||||
playerName = 150,
|
||||
|
||||
//fog of war effect, if applicable
|
||||
fogOfWar = 155,
|
||||
|
||||
//space effects, currently only the land and launch effects
|
||||
space = 160,
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package mindustry.graphics;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.Texture.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
@@ -134,6 +135,23 @@ public class MinimapRenderer{
|
||||
|
||||
Draw.reset();
|
||||
|
||||
if(state.rules.fog){
|
||||
if(withLabels){
|
||||
float z = zoom;
|
||||
//max zoom out fixes everything, somehow?
|
||||
setZoom(99999f);
|
||||
getRegion();
|
||||
zoom = z;
|
||||
}
|
||||
Draw.shader(Shaders.fog);
|
||||
renderer.fog.getTexture().setFilter(TextureFilter.nearest);
|
||||
//crisp pixels
|
||||
Tmp.tr1.set(renderer.fog.getTexture());
|
||||
Tmp.tr1.set(region.u, 1f - region.v, region.u2, 1f - region.v2);
|
||||
Draw.rect(Tmp.tr1, x + w/2f, y + h/2f, w, h);
|
||||
Draw.shader();
|
||||
}
|
||||
|
||||
//TODO might be useful in the standard minimap too
|
||||
if(withLabels){
|
||||
drawSpawns(x, y, w, h, scaling);
|
||||
|
||||
@@ -21,6 +21,7 @@ public class Shaders{
|
||||
public static UnitBuildShader build;
|
||||
public static UnitArmorShader armor;
|
||||
public static DarknessShader darkness;
|
||||
public static FogShader fog;
|
||||
public static LightShader light;
|
||||
public static SurfaceShader water, mud, tar, slag, cryofluid, space, caustics, arkycite;
|
||||
public static PlanetShader planet;
|
||||
@@ -41,6 +42,7 @@ public class Shaders{
|
||||
shield = null;
|
||||
t.printStackTrace();
|
||||
}
|
||||
fog = new FogShader();
|
||||
buildBeam = new BuildBeamShader();
|
||||
build = new UnitBuildShader();
|
||||
armor = new UnitArmorShader();
|
||||
@@ -178,6 +180,12 @@ public class Shaders{
|
||||
}
|
||||
}
|
||||
|
||||
public static class FogShader extends LoadShader{
|
||||
public FogShader(){
|
||||
super("fog", "default");
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated transition class for mods; use UnitBuildShader instead. */
|
||||
@Deprecated
|
||||
public static class UnitBuild extends UnitBuildShader{}
|
||||
|
||||
Reference in New Issue
Block a user