Brief shockwave experiment
This commit is contained in:
42
core/assets/shaders/shockwave.frag
Normal file
42
core/assets/shaders/shockwave.frag
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#define MAX_SHOCKWAVES 64
|
||||||
|
#define WAVE_RADIUS 4.0
|
||||||
|
#define DIFF_SCL 1
|
||||||
|
#define WAVE_POW 0.8
|
||||||
|
|
||||||
|
varying vec2 v_texCoords;
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform vec2 u_resolution;
|
||||||
|
uniform vec2 u_campos;
|
||||||
|
uniform vec4 u_shockwaves[MAX_SHOCKWAVES];
|
||||||
|
uniform int u_shockwave_count;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
vec2 worldCoords = v_texCoords * u_resolution + u_campos;
|
||||||
|
vec2 uv = v_texCoords;
|
||||||
|
vec2 displacement = vec2(0.0, 0.0);
|
||||||
|
|
||||||
|
for(int i = 0; i < MAX_SHOCKWAVES; i ++){
|
||||||
|
vec4 wave = u_shockwaves[i];
|
||||||
|
float radius = wave.z;
|
||||||
|
float strength = wave.w;
|
||||||
|
float dst = distance(worldCoords, wave.xy);
|
||||||
|
float realStrength = 1.0 - pow(1.0 - strength, 5.0);
|
||||||
|
|
||||||
|
if(abs(dst - radius) <= WAVE_RADIUS){
|
||||||
|
float diff = dst - radius;
|
||||||
|
float pdiff = 1.0 - pow(abs(diff * DIFF_SCL), WAVE_POW);
|
||||||
|
float diffTime = diff * pdiff;
|
||||||
|
vec2 relative = normalize(worldCoords - wave.xy);
|
||||||
|
|
||||||
|
displacement += (relative * diffTime * strength) / u_resolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i >= u_shockwave_count - 1){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 c = texture2D(u_texture, uv + displacement);
|
||||||
|
gl_FragColor = c;
|
||||||
|
}
|
||||||
@@ -85,6 +85,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
transient float efficiency;
|
transient float efficiency;
|
||||||
/** Same as efficiency, but for optional consumers only. */
|
/** Same as efficiency, but for optional consumers only. */
|
||||||
transient float optionalEfficiency;
|
transient float optionalEfficiency;
|
||||||
|
/** The efficiency this block would have if consValid() / productionValid() returned true. */
|
||||||
|
transient float potentialEfficiency;
|
||||||
|
|
||||||
transient float healSuppressionTime = -1f;
|
transient float healSuppressionTime = -1f;
|
||||||
transient float lastHealTime = -120f * 10f;
|
transient float lastHealTime = -120f * 10f;
|
||||||
@@ -224,7 +226,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
|
|
||||||
//version 3 has efficiency numbers instead of bools
|
//version 3 has efficiency numbers instead of bools
|
||||||
if(version >= 3){
|
if(version >= 3){
|
||||||
efficiency = read.ub() / 255f;
|
efficiency = potentialEfficiency = read.ub() / 255f;
|
||||||
optionalEfficiency = read.ub() / 255f;
|
optionalEfficiency = read.ub() / 255f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1640,7 +1642,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean canConsume(){
|
public boolean canConsume(){
|
||||||
return efficiency > 0;
|
return potentialEfficiency > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Scaled delta. */
|
/** Scaled delta. */
|
||||||
@@ -1671,40 +1673,43 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
public void updateConsumption(){
|
public void updateConsumption(){
|
||||||
//everything is valid when cheating
|
//everything is valid when cheating
|
||||||
if(!block.hasConsumers || cheating()){
|
if(!block.hasConsumers || cheating()){
|
||||||
efficiency = optionalEfficiency = 1f;
|
potentialEfficiency = efficiency = optionalEfficiency = 1f;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//disabled -> nothing works
|
//disabled -> nothing works
|
||||||
if(!enabled){
|
if(!enabled){
|
||||||
efficiency = optionalEfficiency = 0f;
|
potentialEfficiency = efficiency = optionalEfficiency = 0f;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO why check for old state?
|
//TODO why check for old state?
|
||||||
boolean prevValid = efficiency > 0, update = shouldConsume() && productionValid();
|
boolean prevValid = efficiency > 0, update = shouldConsume() && productionValid();
|
||||||
|
|
||||||
if(update){
|
float minEfficiency = 1f;
|
||||||
float minEfficiency = 1f;
|
|
||||||
|
|
||||||
//assume efficiency is 1 for the calculations below
|
//assume efficiency is 1 for the calculations below
|
||||||
efficiency = optionalEfficiency = 1f;
|
efficiency = optionalEfficiency = 1f;
|
||||||
|
|
||||||
//first pass: get the minimum efficiency of any consumer
|
//first pass: get the minimum efficiency of any consumer
|
||||||
for(var cons : block.nonOptionalConsumers){
|
for(var cons : block.nonOptionalConsumers){
|
||||||
minEfficiency = Math.min(minEfficiency, cons.efficiency(self()));
|
minEfficiency = Math.min(minEfficiency, cons.efficiency(self()));
|
||||||
}
|
}
|
||||||
|
|
||||||
//same for optionals
|
//same for optionals
|
||||||
for(var cons : block.optionalConsumers){
|
for(var cons : block.optionalConsumers){
|
||||||
optionalEfficiency = Math.min(optionalEfficiency, cons.efficiency(self()));
|
optionalEfficiency = Math.min(optionalEfficiency, cons.efficiency(self()));
|
||||||
}
|
}
|
||||||
|
|
||||||
//efficiency is now this minimum value
|
//efficiency is now this minimum value
|
||||||
efficiency = minEfficiency;
|
efficiency = minEfficiency;
|
||||||
optionalEfficiency = Math.min(optionalEfficiency, minEfficiency);
|
optionalEfficiency = Math.min(optionalEfficiency, minEfficiency);
|
||||||
}else{
|
|
||||||
//should not consume, efficiency now zero
|
//assign "potential"
|
||||||
|
potentialEfficiency = efficiency;
|
||||||
|
|
||||||
|
//no updating means zero efficiency
|
||||||
|
if(!update){
|
||||||
efficiency = optionalEfficiency = 0f;
|
efficiency = optionalEfficiency = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ import arc.graphics.g3d.*;
|
|||||||
import arc.graphics.gl.*;
|
import arc.graphics.gl.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
@@ -28,6 +30,7 @@ public class Shaders{
|
|||||||
public static CloudShader clouds;
|
public static CloudShader clouds;
|
||||||
public static PlanetGridShader planetGrid;
|
public static PlanetGridShader planetGrid;
|
||||||
public static AtmosphereShader atmosphere;
|
public static AtmosphereShader atmosphere;
|
||||||
|
public static ShockwaveShader shockwave;
|
||||||
public static MeshShader mesh;
|
public static MeshShader mesh;
|
||||||
public static Shader unlit;
|
public static Shader unlit;
|
||||||
public static Shader screenspace;
|
public static Shader screenspace;
|
||||||
@@ -67,6 +70,9 @@ public class Shaders{
|
|||||||
atmosphere = new AtmosphereShader();
|
atmosphere = new AtmosphereShader();
|
||||||
unlit = new LoadShader("planet", "unlit");
|
unlit = new LoadShader("planet", "unlit");
|
||||||
screenspace = new LoadShader("screenspace", "screenspace");
|
screenspace = new LoadShader("screenspace", "screenspace");
|
||||||
|
|
||||||
|
//disabled for now...
|
||||||
|
//shockwave = new ShockwaveShader();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AtmosphereShader extends LoadShader{
|
public static class AtmosphereShader extends LoadShader{
|
||||||
@@ -350,6 +356,112 @@ public class Shaders{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ShockwaveShader extends LoadShader{
|
||||||
|
static final int max = 64;
|
||||||
|
static final int size = 5;
|
||||||
|
static final String[] uniformNames = new String[max];
|
||||||
|
|
||||||
|
//x y radius life[1-0] lifetime
|
||||||
|
protected FloatSeq data = new FloatSeq();
|
||||||
|
protected boolean hadAny = false;
|
||||||
|
protected FrameBuffer buffer = new FrameBuffer();
|
||||||
|
|
||||||
|
public float lifetime = 20f;
|
||||||
|
|
||||||
|
static{
|
||||||
|
for(int i = 0; i < max; i++){
|
||||||
|
uniformNames[i] = "u_shockwaves[" + i + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShockwaveShader(){
|
||||||
|
super("shockwave", "screenspace");
|
||||||
|
|
||||||
|
Events.run(Trigger.update, () -> {
|
||||||
|
if(state.isPaused()) return;
|
||||||
|
if(state.isMenu()){
|
||||||
|
data.size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = data.items;
|
||||||
|
for(int i = 0; i < data.size; i += size){
|
||||||
|
//decrease lifetime
|
||||||
|
items[i + 3] -= Time.delta / items[i + 4];
|
||||||
|
|
||||||
|
if(items[i + 3] <= 0f){
|
||||||
|
//swap with head.
|
||||||
|
if(data.size > size){
|
||||||
|
System.arraycopy(items, data.size - size, items, i, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.size -= size;
|
||||||
|
i -= size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Events.run(Trigger.preDraw, () -> {
|
||||||
|
hadAny = data.size > 0;
|
||||||
|
|
||||||
|
if(hadAny){
|
||||||
|
buffer.resize(Core.graphics.getWidth(), Core.graphics.getHeight());
|
||||||
|
buffer.begin(Color.clear);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Events.run(Trigger.postDraw, () -> {
|
||||||
|
if(hadAny){
|
||||||
|
buffer.end();
|
||||||
|
Draw.blend(Blending.disabled);
|
||||||
|
buffer.blit(this);
|
||||||
|
Draw.blend();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(){
|
||||||
|
int count = data.size / 4;
|
||||||
|
|
||||||
|
setUniformi("u_shockwave_count", count);
|
||||||
|
if(count > 0){
|
||||||
|
setUniformf("u_resolution", Core.camera.width, Core.camera.height);
|
||||||
|
setUniformf("u_campos", Core.camera.position.x - Core.camera.width/2f, Core.camera.position.y - Core.camera.height/2f);
|
||||||
|
|
||||||
|
var items = data.items;
|
||||||
|
for(int i = 0; i < count; i++){
|
||||||
|
int offset = i * size;
|
||||||
|
|
||||||
|
setUniformf(uniformNames[i],
|
||||||
|
items[offset], items[offset + 1], //xy
|
||||||
|
items[offset + 2] * (1f - items[offset + 3]), //radius * time
|
||||||
|
items[offset + 3] //time
|
||||||
|
//lifetime ignored
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(float x, float y, float radius){
|
||||||
|
add(x, y, radius, 20f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(float x, float y, float radius, float lifetime){
|
||||||
|
//replace first entry
|
||||||
|
if(data.size / size >= max){
|
||||||
|
var items = data.items;
|
||||||
|
items[0] = x;
|
||||||
|
items[1] = y;
|
||||||
|
items[2] = radius;
|
||||||
|
items[3] = 1f;
|
||||||
|
items[4] = lifetime;
|
||||||
|
}else{
|
||||||
|
data.addAll(x, y, radius, 1f, lifetime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class LoadShader extends Shader{
|
public static class LoadShader extends Shader{
|
||||||
public LoadShader(String frag, String vert){
|
public LoadShader(String frag, String vert){
|
||||||
super(getShaderFi(vert + ".vert"), getShaderFi(frag + ".frag"));
|
super(getShaderFi(vert + ".vert"), getShaderFi(frag + ".frag"));
|
||||||
|
|||||||
@@ -331,13 +331,13 @@ public class Turret extends ReloadTurret{
|
|||||||
//turret always reloads regardless of whether it's targeting something
|
//turret always reloads regardless of whether it's targeting something
|
||||||
updateReload();
|
updateReload();
|
||||||
|
|
||||||
if(timer(timerTarget, targetInterval)){
|
|
||||||
findTarget();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hasAmmo()){
|
if(hasAmmo()){
|
||||||
if(Float.isNaN(reloadCounter)) reloadCounter = 0;
|
if(Float.isNaN(reloadCounter)) reloadCounter = 0;
|
||||||
|
|
||||||
|
if(timer(timerTarget, targetInterval)){
|
||||||
|
findTarget();
|
||||||
|
}
|
||||||
|
|
||||||
if(validateTarget()){
|
if(validateTarget()){
|
||||||
boolean canShoot = true;
|
boolean canShoot = true;
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ public class Turret extends ReloadTurret{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void turnToTarget(float targetRot){
|
protected void turnToTarget(float targetRot){
|
||||||
rotation = Angles.moveToward(rotation, targetRot, rotateSpeed * delta() * baseReloadSpeed());
|
rotation = Angles.moveToward(rotation, targetRot, rotateSpeed * delta() * potentialEfficiency);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldTurn(){
|
public boolean shouldTurn(){
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class CoreBlock extends StorageBlock{
|
|||||||
public void init(){
|
public void init(){
|
||||||
//assign to update clipSize internally
|
//assign to update clipSize internally
|
||||||
lightRadius = 30f + 20f * size;
|
lightRadius = 30f + 20f * size;
|
||||||
fogRadius = Math.max(fogRadius, (int)(lightRadius / 8f * 3f) + 5);
|
fogRadius = Math.max(fogRadius, (int)(lightRadius / 8f * 3f) + 13);
|
||||||
emitLight = true;
|
emitLight = true;
|
||||||
|
|
||||||
super.init();
|
super.init();
|
||||||
|
|||||||
Reference in New Issue
Block a user