Better projector gui

This commit is contained in:
JozsefA 2021-04-22 23:42:49 -07:00
parent fc919c4ac4
commit 3879d55517
14 changed files with 300 additions and 171 deletions

View file

@ -1153,6 +1153,7 @@
"create.gui.chromatic_projector.filter.grayscale": "Grayscale", "create.gui.chromatic_projector.filter.grayscale": "Grayscale",
"create.gui.chromatic_projector.filter.saturate": "Saturate", "create.gui.chromatic_projector.filter.saturate": "Saturate",
"create.gui.chromatic_projector.filter.hue_shift": "Hue shift", "create.gui.chromatic_projector.filter.hue_shift": "Hue shift",
"create.gui.chromatic_projector.filter.darken": "Darken",
"create.gui.chromatic_projector.filter.end": "End", "create.gui.chromatic_projector.filter.end": "End",
"create.gui.chromatic_projector.filter": "Filter", "create.gui.chromatic_projector.filter": "Filter",
"_": "->------------------------] Subtitles [------------------------<-", "_": "->------------------------] Subtitles [------------------------<-",

View file

@ -116,6 +116,7 @@ import com.simibubi.create.content.contraptions.relays.gearbox.GearboxInstance;
import com.simibubi.create.content.contraptions.relays.gearbox.GearboxRenderer; import com.simibubi.create.content.contraptions.relays.gearbox.GearboxRenderer;
import com.simibubi.create.content.contraptions.relays.gearbox.GearboxTileEntity; import com.simibubi.create.content.contraptions.relays.gearbox.GearboxTileEntity;
import com.simibubi.create.content.contraptions.relays.gearbox.GearshiftTileEntity; import com.simibubi.create.content.contraptions.relays.gearbox.GearshiftTileEntity;
import com.simibubi.create.content.curiosities.projector.ChromaticProjectorInstance;
import com.simibubi.create.content.curiosities.projector.ChromaticProjectorTileEntity; import com.simibubi.create.content.curiosities.projector.ChromaticProjectorTileEntity;
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelInstance; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelInstance;
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelRenderer; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelRenderer;
@ -646,21 +647,23 @@ public class AllTileEntities {
.instance(() -> AdjustableRepeaterInstance::new) .instance(() -> AdjustableRepeaterInstance::new)
.validBlocks(AllBlocks.ADJUSTABLE_REPEATER) .validBlocks(AllBlocks.ADJUSTABLE_REPEATER)
.renderer(() -> AdjustableRepeaterRenderer::new) .renderer(() -> AdjustableRepeaterRenderer::new)
.register(); .register();
public static final TileEntityEntry<AdjustablePulseRepeaterTileEntity> ADJUSTABLE_PULSE_REPEATER = public static final TileEntityEntry<AdjustablePulseRepeaterTileEntity> ADJUSTABLE_PULSE_REPEATER =
Create.registrate() Create.registrate()
.tileEntity("adjustable_pulse_repeater", AdjustablePulseRepeaterTileEntity::new) .tileEntity("adjustable_pulse_repeater", AdjustablePulseRepeaterTileEntity::new)
.instance(() -> AdjustableRepeaterInstance::new) .instance(() -> AdjustableRepeaterInstance::new)
.validBlocks(AllBlocks.ADJUSTABLE_PULSE_REPEATER) .validBlocks(AllBlocks.ADJUSTABLE_PULSE_REPEATER)
.renderer(() -> AdjustableRepeaterRenderer::new) .renderer(() -> AdjustableRepeaterRenderer::new)
.register(); .register();
public static final TileEntityEntry<ChromaticProjectorTileEntity> TESTFX = public static final TileEntityEntry<ChromaticProjectorTileEntity> CHROMATIC_PROJECTOR =
Create.registrate() Create.registrate()
.tileEntity("chromatic_projector", ChromaticProjectorTileEntity::new) .tileEntity("chromatic_projector", ChromaticProjectorTileEntity::new)
.validBlocks(AllBlocks.CHROMATIC_PROJECTOR) .instance(() -> ChromaticProjectorInstance::new)
.register(); .validBlocks(AllBlocks.CHROMATIC_PROJECTOR)
.register();
public static void register() {} public static void register() {
}
} }

View file

@ -54,7 +54,7 @@ public class ChromaticProjectorBlock extends Block implements ITE<ChromaticProje
@Nullable @Nullable
@Override @Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) { public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return AllTileEntities.TESTFX.create(); return AllTileEntities.CHROMATIC_PROJECTOR.create();
} }
@Override @Override

View file

@ -0,0 +1,28 @@
package com.simibubi.create.content.curiosities.projector;
import com.simibubi.create.foundation.render.backend.Backend;
import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.foundation.render.backend.instancing.TileEntityInstance;
public class ChromaticProjectorInstance extends TileEntityInstance<ChromaticProjectorTileEntity> implements IDynamicInstance {
public ChromaticProjectorInstance(InstancedTileRenderer<?> renderer, ChromaticProjectorTileEntity tile) {
super(renderer, tile);
}
@Override
public void beginFrame() {
Backend.effects.addSphere(tile.makeFilter());
}
@Override
public boolean decreaseFramerateWithDistance() {
return false;
}
@Override
public void remove() {
}
}

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.curiosities.projector; package com.simibubi.create.content.curiosities.projector;
import java.util.Collections;
import java.util.Vector; import java.util.Vector;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
@ -11,6 +12,7 @@ import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.widgets.IconButton; import com.simibubi.create.foundation.gui.widgets.IconButton;
import com.simibubi.create.foundation.gui.widgets.ScrollInput; import com.simibubi.create.foundation.gui.widgets.ScrollInput;
import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput; import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -35,12 +37,24 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen {
private Vector<Vector<ScrollInput>> inputs; private Vector<Vector<ScrollInput>> inputs;
ChromaticProjectorTileEntity tile;
private ScrollInput radius;
private ScrollInput density;
private ScrollInput feather;
private ScrollInput fade;
public ChromaticProjectorScreen(ChromaticProjectorTileEntity te) { public ChromaticProjectorScreen(ChromaticProjectorTileEntity te) {
this.tile = te;
this.stages = te.stages; this.stages = te.stages;
this.pos = te.getPos(); this.pos = te.getPos();
//compareTag = Instruction.serializeAll(stages); //compareTag = Instruction.serializeAll(stages);
} }
private static Integer step(ScrollValueBehaviour.StepContext ctx, int base) {
return ctx.control ? 1 : base * (ctx.shift ? 5 : 1);
}
@Override @Override
protected void init() { protected void init() {
setWindowSize(background.width + 50, background.height); setWindowSize(background.width + 50, background.height);
@ -57,6 +71,32 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen {
confirmButton = confirmButton =
new IconButton(guiLeft + background.width - 33, guiTop + background.height - 24, AllIcons.I_CONFIRM); new IconButton(guiLeft + background.width - 33, guiTop + background.height - 24, AllIcons.I_CONFIRM);
widgets.add(confirmButton); widgets.add(confirmButton);
radius = new ScrollInput(guiLeft + 46, guiTop + 117, 28, 18)
.titled(new StringTextComponent("Radius"))
.withStepFunction(ctx -> step(ctx, 2))
.calling(tile::setRadius)
.withRange(0, 201)
.setState((int) (tile.radius * 2));
feather = new ScrollInput(guiLeft + 46, guiTop + 139, 28, 18)
.titled(new StringTextComponent("Feather"))
.withStepFunction(ctx -> step(ctx, 5))
.calling(tile::setFeather)
.withRange(0, 201)
.setState((int) (tile.feather * 4));
fade = new ScrollInput(guiLeft + 117, guiTop + 139, 28, 18)
.titled(new StringTextComponent("Fade"))
.withStepFunction(ctx -> step(ctx, 1))
.calling(tile::setFade)
.withRange(0, 51)
.setState((int) (tile.fade * 10));
density = new ScrollInput(guiLeft + 117, guiTop + 117, 28, 18)
.titled(new StringTextComponent("Density"))
.withStepFunction(ctx -> step(ctx, 10))
.calling(tile::setDensity)
.withRange(0, 401)
.setState((int) (tile.density * 100));
Collections.addAll(widgets, radius, density, feather, fade);
} }
public void initInputsOfRow(int row) { public void initInputsOfRow(int row) {
@ -73,10 +113,11 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen {
ScrollInput type = ScrollInput type =
new SelectionScrollInput(x, y + rowHeight * row, 86, 18).forOptions(ColorEffects.getOptions()) new SelectionScrollInput(x, y + rowHeight * row, 86, 18).forOptions(ColorEffects.getOptions())
.calling(state -> instructionUpdated(index, state)) .calling(state -> instructionUpdated(index, state))
.setState(instruction.instruction.ordinal()) .setState(instruction.filter.ordinal())
.titled(Lang.translate("gui.chromatic_projector.filter")); .titled(Lang.translate("gui.chromatic_projector.filter"));
ScrollInput value = ScrollInput value =
new ScrollInput(x + 86 + 2, y + rowHeight * row, 28, 18).calling(state -> instruction.value = state); new ScrollInput(x + 86 + 2, y + rowHeight * row, 28, 18)
.calling(state -> instruction.value = state);
rowInputs.add(type); rowInputs.add(type);
rowInputs.add(value); rowInputs.add(value);
@ -88,15 +129,15 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen {
public void updateParamsOfRow(int row) { public void updateParamsOfRow(int row) {
FilterStep instruction = stages.get(row); FilterStep instruction = stages.get(row);
Vector<ScrollInput> rowInputs = inputs.get(row); Vector<ScrollInput> rowInputs = inputs.get(row);
ColorEffects def = instruction.instruction; ColorEffects def = instruction.filter;
boolean hasValue = def.hasParameter; boolean hasValue = def.hasParameter;
ScrollInput value = rowInputs.get(1); ScrollInput value = rowInputs.get(1);
value.active = value.visible = hasValue; value.active = value.visible = hasValue;
if (hasValue) if (hasValue)
value.withRange(0, 100) value.withRange(def.minValue, def.maxValue + 1)
//.titled(Lang.translate(def.parameterKey)) //.titled(Lang.translate(def.parameterKey))
//.withShiftStep(def.shiftStep) .withShiftStep(5)
.setState(instruction.value) .setState(instruction.value)
.onChanged(); .onChanged();
@ -116,36 +157,47 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen {
continue; continue;
} }
FilterStep instruction = stages.get(row); FilterStep step = stages.get(row);
ColorEffects def = instruction.instruction; ColorEffects def = step.filter;
def.background.draw(matrixStack, guiLeft, guiTop + 14 + yOffset); def.background.draw(matrixStack, guiLeft, guiTop + 14 + yOffset);
label(matrixStack, 36, yOffset - 3, Lang.translate(def.translationKey)); if (def != ColorEffects.END)
label(matrixStack, 36, yOffset - 3, Lang.translate(def.translationKey));
if (def.hasParameter) { if (def.hasParameter) {
String text = instruction.value + " %"; String text = step.filter.formatValue(step.value);
int stringWidth = textRenderer.getStringWidth(text); int stringWidth = textRenderer.getStringWidth(text);
label(matrixStack, 118 + (12 - stringWidth / 2), yOffset - 3, new StringTextComponent(text)); label(matrixStack, 118 + (12 - stringWidth / 2), yOffset - 3, new StringTextComponent(text));
} }
} }
renderScroll(matrixStack, radius, 2f);
renderScroll(matrixStack, density, 100f);
renderScroll(matrixStack, feather, 4f);
renderScroll(matrixStack, fade, 10f);
textRenderer.drawWithShadow(matrixStack, title, guiLeft - 3 + (background.width - textRenderer.getWidth(title)) / 2, guiTop + 3, textRenderer.drawWithShadow(matrixStack, title, guiLeft - 3 + (background.width - textRenderer.getWidth(title)) / 2, guiTop + 3,
0xffffff); 0xffffff);
GuiGameElement.of(renderedItem) GuiGameElement.of(renderedItem)
.at(guiLeft + background.width + 10, guiTop + 100, -150) .at(guiLeft + background.width + 10, guiTop + 140, -150)
.scale(5) .scale(5)
.render(matrixStack); .render(matrixStack);
} }
private void renderScroll(MatrixStack matrixStack, ScrollInput input, float divisor) {
String text = String.valueOf(input.getState() / divisor);
int stringWidth = textRenderer.getStringWidth(text);
textRenderer.drawWithShadow(matrixStack, text, input.x + (12 - stringWidth / 2), input.y + 5, 0xFFFFEE);
}
private void label(MatrixStack matrixStack, int x, int y, ITextComponent text) { private void label(MatrixStack matrixStack, int x, int y, ITextComponent text) {
textRenderer.drawWithShadow(matrixStack, text, guiLeft + x, guiTop + 26 + y, 0xFFFFEE); textRenderer.drawWithShadow(matrixStack, text, guiLeft + x, guiTop + 26 + y, 0xFFFFEE);
} }
public void sendPacket() { public void sendPacket() {
// ListNBT serialized = Instruction.serializeAll(stages);
// if (serialized.equals(compareTag))
// return;
// AllPackets.channel.sendToServer(new ConfigureSequencedGearshiftPacket(pos, serialized));
} }
@Override @Override
@ -155,7 +207,7 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen {
private void instructionUpdated(int index, int state) { private void instructionUpdated(int index, int state) {
ColorEffects newValue = ColorEffects.values()[state]; ColorEffects newValue = ColorEffects.values()[state];
stages.get(index).instruction = newValue; stages.get(index).filter = newValue;
stages.get(index).value = 100; stages.get(index).value = 100;
updateParamsOfRow(index); updateParamsOfRow(index);
if (newValue == ColorEffects.END) { if (newValue == ColorEffects.END) {

View file

@ -2,14 +2,64 @@ package com.simibubi.create.content.curiosities.projector;
import java.util.Vector; import java.util.Vector;
import com.simibubi.create.foundation.render.backend.effects.SphereFilterProgram;
import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Matrix4f;
public class ChromaticProjectorTileEntity extends TileEntity { public class ChromaticProjectorTileEntity extends TileEntity implements IInstanceRendered {
Vector<FilterStep> stages = FilterStep.createDefault(); Vector<FilterStep> stages = FilterStep.createDefault();
float radius = 10f;
float density = 1f;
float feather = 3;
float fade = 1.3f;
boolean blend = true;
public ChromaticProjectorTileEntity(TileEntityType<?> te) { public ChromaticProjectorTileEntity(TileEntityType<?> te) {
super(te); super(te);
} }
public SphereFilterProgram.FilterSphere makeFilter() {
Matrix4f filter = FilterStep.fold(stages);
BlockPos pos = getPos();
return new SphereFilterProgram.FilterSphere()
.setFilter(filter)
.setCenter(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5)
.setRadius(radius)
.setDensity(density)
.setFeather(feather)
.setBlendOver(false)
.setFade(fade);
}
public ChromaticProjectorTileEntity setRadius(int radius) {
this.radius = radius / 2f;
return this;
}
public ChromaticProjectorTileEntity setDensity(int density) {
this.density = density / 100f;
return this;
}
public ChromaticProjectorTileEntity setFeather(int feather) {
this.feather = feather / 4f;
return this;
}
public ChromaticProjectorTileEntity setFade(int fade) {
this.fade = feather / 10f;
return this;
}
public ChromaticProjectorTileEntity setBlend(boolean blend) {
this.blend = blend;
return this;
}
} }

View file

@ -15,8 +15,9 @@ public enum ColorEffects {
INVERT(ColorMatrices::invert), INVERT(ColorMatrices::invert),
SEPIA(ColorMatrices::sepia), SEPIA(ColorMatrices::sepia),
GRAYSCALE(ColorMatrices::grayscale), GRAYSCALE(ColorMatrices::grayscale),
SATURATE(ColorMatrices::saturate), DARKEN(ColorMatrices::darken),
HUE_SHIFT(ColorMatrices::hueShift), SATURATE(ColorMatrices::saturate, 0, 200),
HUE_SHIFT(ColorMatrices::hueShift, 0, 360, 1f),
END(ColorMatrices::identity, AllGuiTextures.PROJECTOR_END), END(ColorMatrices::identity, AllGuiTextures.PROJECTOR_END),
; ;
@ -26,6 +27,10 @@ public enum ColorEffects {
String translationKey; String translationKey;
AllGuiTextures background; AllGuiTextures background;
int minValue = 0;
int maxValue = 100;
float divisor = 100f;
ColorEffects(Supplier<Matrix4f> filter, AllGuiTextures background) { ColorEffects(Supplier<Matrix4f> filter, AllGuiTextures background) {
this($ -> filter.get(), false, background); this($ -> filter.get(), false, background);
} }
@ -35,7 +40,18 @@ public enum ColorEffects {
} }
ColorEffects(FilterFactory filter) { ColorEffects(FilterFactory filter) {
this(filter, 0, 100);
}
ColorEffects(FilterFactory filter, int minValue, int maxValue) {
this(filter, minValue, maxValue, 100f);
}
ColorEffects(FilterFactory filter, int minValue, int maxValue, float divisor) {
this(filter, true, AllGuiTextures.PROJECTOR_FILTER_STRENGTH); this(filter, true, AllGuiTextures.PROJECTOR_FILTER_STRENGTH);
this.minValue = minValue;
this.maxValue = maxValue;
this.divisor = divisor;
} }
ColorEffects(FilterFactory filter, boolean hasParameter, AllGuiTextures background) { ColorEffects(FilterFactory filter, boolean hasParameter, AllGuiTextures background) {
@ -45,6 +61,12 @@ public enum ColorEffects {
translationKey = "gui.chromatic_projector.filter." + Lang.asId(name()); translationKey = "gui.chromatic_projector.filter." + Lang.asId(name());
} }
String formatValue(int value) {
if (this == HUE_SHIFT)
return value + Lang.translate("generic.unit.degrees").getString();
return "" + value;
}
static List<ITextComponent> getOptions() { static List<ITextComponent> getOptions() {
List<ITextComponent> options = new ArrayList<>(); List<ITextComponent> options = new ArrayList<>();
for (ColorEffects entry : values()) for (ColorEffects entry : values())

View file

@ -1,21 +1,44 @@
package com.simibubi.create.content.curiosities.projector; package com.simibubi.create.content.curiosities.projector;
import java.util.Iterator;
import java.util.Vector; import java.util.Vector;
import com.simibubi.create.foundation.render.backend.effects.ColorMatrices;
import net.minecraft.util.math.vector.Matrix4f;
public class FilterStep { public class FilterStep {
ColorEffects instruction; ColorEffects filter;
int value; int value;
public FilterStep(ColorEffects instruction) { public FilterStep(ColorEffects filter) {
this.instruction = instruction; this.filter = filter;
} }
public FilterStep(ColorEffects instruction, int value) { public FilterStep(ColorEffects filter, int value) {
this.instruction = instruction; this.filter = filter;
this.value = value; this.value = value;
} }
public Matrix4f createFilter() {
return filter.filter.create(value / filter.divisor);
}
public static Matrix4f fold(Vector<FilterStep> filters) {
Iterator<FilterStep> stepIterator = filters.stream().filter(it -> it != null && it.filter != ColorEffects.END).iterator();
if (stepIterator.hasNext()) {
Matrix4f accum = stepIterator.next().createFilter();
stepIterator.forEachRemaining(filterStep -> accum.multiply(filterStep.createFilter()));
return accum;
}
return ColorMatrices.identity();
}
public static Vector<FilterStep> createDefault() { public static Vector<FilterStep> createDefault() {
Vector<FilterStep> instructions = new Vector<>(ChromaticProjectorScreen.MAX_STEPS); Vector<FilterStep> instructions = new Vector<>(ChromaticProjectorScreen.MAX_STEPS);
instructions.add(new FilterStep(ColorEffects.SEPIA, 100)); instructions.add(new FilterStep(ColorEffects.SEPIA, 100));

View file

@ -92,6 +92,16 @@ public class ColorMatrices {
return mat; return mat;
} }
public static Matrix4f darken(float amount) {
Matrix4f darken = new Matrix4f();
darken.loadIdentity();
darken.multiply(1f - amount);
darken.a03 = amount;
darken.a13 = amount;
darken.a23 = amount;
return darken;
}
public static Matrix4f identity() { public static Matrix4f identity() {
Matrix4f mat = new Matrix4f(); Matrix4f mat = new Matrix4f();
mat.loadIdentity(); mat.loadIdentity();

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.render.backend.effects; package com.simibubi.create.foundation.render.backend.effects;
import java.util.ArrayList;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL20;
@ -14,6 +16,7 @@ import com.simibubi.create.foundation.utility.AnimationTickHolder;
import net.minecraft.client.MainWindow; import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.shader.Framebuffer; import net.minecraft.client.shader.Framebuffer;
import net.minecraft.client.shader.FramebufferConstants; import net.minecraft.client.shader.FramebufferConstants;
@ -48,7 +51,11 @@ public class EffectsHandler {
private final GlBuffer vbo = new GlBuffer(GL20.GL_ARRAY_BUFFER); private final GlBuffer vbo = new GlBuffer(GL20.GL_ARRAY_BUFFER);
private final ArrayList<SphereFilterProgram.FilterSphere> spheres;
public EffectsHandler() { public EffectsHandler() {
spheres = new ArrayList<>();
Framebuffer render = Minecraft.getInstance().getFramebuffer(); Framebuffer render = Minecraft.getInstance().getFramebuffer();
framebuffer = new Framebuffer(render.framebufferWidth, render.framebufferHeight, false, Minecraft.IS_RUNNING_ON_MAC); framebuffer = new Framebuffer(render.framebufferWidth, render.framebufferHeight, false, Minecraft.IS_RUNNING_ON_MAC);
@ -64,21 +71,17 @@ public class EffectsHandler {
vao.unbind(); vao.unbind();
vbo.unbind(); vbo.unbind();
} }
public void prepFramebufferSize() { public void addSphere(SphereFilterProgram.FilterSphere sphere) {
MainWindow window = Minecraft.getInstance().getWindow(); this.spheres.add(sphere);
if (framebuffer.framebufferWidth != window.getFramebufferWidth()
|| framebuffer.framebufferHeight != window.getFramebufferHeight()) {
framebuffer.func_216491_a(window.getFramebufferWidth(), window.getFramebufferHeight(),
Minecraft.IS_RUNNING_ON_MAC);
}
} }
public void render(Matrix4f view) { public void render(Matrix4f view) {
// if (true) { if (spheres.size() == 0) {
// return; return;
// } }
GL20.glEnable(GL20.GL_DEPTH_TEST); GL20.glEnable(GL20.GL_DEPTH_TEST);
@ -98,7 +101,8 @@ public class EffectsHandler {
program.bindDepthTexture(mainBuffer.getDepthAttachment()); program.bindDepthTexture(mainBuffer.getDepthAttachment());
GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer; GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer;
Matrix4f projection = gameRenderer.getBasicProjectionMatrix(gameRenderer.getActiveRenderInfo(), AnimationTickHolder.getPartialTicks(), true); ActiveRenderInfo activeRenderInfo = gameRenderer.getActiveRenderInfo();
Matrix4f projection = gameRenderer.getBasicProjectionMatrix(activeRenderInfo, AnimationTickHolder.getPartialTicks(), true);
projection.a33 = 1; projection.a33 = 1;
projection.invert(); projection.invert();
program.bindInverseProjection(projection); program.bindInverseProjection(projection);
@ -107,76 +111,17 @@ public class EffectsHandler {
inverseView.invert(); inverseView.invert();
program.bindInverseView(inverseView); program.bindInverseView(inverseView);
Vector3d cameraPos = gameRenderer.getActiveRenderInfo().getProjectedView(); Vector3d cameraPos = activeRenderInfo.getProjectedView();
program.setCameraPos(cameraPos.inverse()); program.setCameraPos(cameraPos.inverse());
// int n = 64; for (SphereFilterProgram.FilterSphere sphere : spheres) {
// double rad = 15; sphere.center = sphere.center.subtract(cameraPos);
// for (int i = 0; i < n; i++) { }
// double angle = ((double) i) / n * Math.PI * 2;
// program.addSphere(new SphereFilterProgram.FilterSphere()
// .setCenter(new Vector3d(852, 77, -204).subtract(cameraPos).add(Math.sin(angle) * rad, 0, Math.cos(angle) * rad))
// .setRadius(15)
// .setFeather(3f)
// .setFade(1f)
// .setDensity(0.5f)
// .setFilter(ColorMatrices.hueShiftRGB((float) i / n * 360 + i / 2f)));
// }
program.addSphere(new SphereFilterProgram.FilterSphere() spheres.sort((o1, o2) -> (int) Math.signum(o2.center.length() - o1.center.length()));
.setCenter(new Vector3d(865.5, 79, -240.5).subtract(cameraPos))
.setRadius(10f)
.setFeather(3f)
.setFade(1.8f)
.setDensity(1.3f)
.setFilter(ColorMatrices.grayscale()));
program.addSphere(new SphereFilterProgram.FilterSphere() program.uploadFilters(spheres);
.setCenter(new Vector3d(852.5, 70, -203.5).subtract(cameraPos))
.setRadius(20f)
.setFeather(3f)
.setFade(1f)
.setDensity(1.3f)
.setFilter(ColorMatrices.sepia(1f)));
// Matrix4f test = ColorMatrices.sepia(1f);
//
//
// test.multiply(ColorMatrices.invert());
//
// Matrix4f darken = new Matrix4f();
// darken.loadIdentity();
// darken.multiply(0.7f);
// darken.a03 = 0.7f;
// darken.a13 = 0.7f;
// darken.a23 = 0.7f;
// test.multiply(darken);
Matrix4f test = ColorMatrices.saturate(2f);
test.multiply(ColorMatrices.hueShift(120f));
program.addSphere(new SphereFilterProgram.FilterSphere()
.setCenter(new Vector3d(858.5, 88, -259.5).subtract(cameraPos))
.setRadius(10f)
.setFeather(3f)
.setFade(1.8f)
.setDensity(0.5f)
.setStrength(1f)
.setFilter(test));
program.addSphere(new SphereFilterProgram.FilterSphere()
.setCenter(new Vector3d(2310, 60, -954).subtract(cameraPos))
.setRadius(8f)
.setFeather(3f)
.setFade(0.8f)
.setDensity(1.3f)
.setStrength(1f)
.setFilter(ColorMatrices.grayscale()));
program.uploadFilters();
program.setFarPlane(getFarPlane()); program.setFarPlane(getFarPlane());
program.setNearPlane(getNearPlane()); program.setNearPlane(getNearPlane());
@ -189,8 +134,8 @@ public class EffectsHandler {
program.bindDepthTexture(0); program.bindDepthTexture(0);
GL20.glActiveTexture(GL20.GL_TEXTURE0); GL20.glActiveTexture(GL20.GL_TEXTURE0);
program.clear();
program.unbind(); program.unbind();
spheres.clear();
Backend.compat.fbo.bindFramebuffer(GL30.GL_READ_FRAMEBUFFER, framebuffer.framebufferObject); Backend.compat.fbo.bindFramebuffer(GL30.GL_READ_FRAMEBUFFER, framebuffer.framebufferObject);
Backend.compat.fbo.bindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, mainBuffer.framebufferObject); Backend.compat.fbo.bindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, mainBuffer.framebufferObject);
@ -204,4 +149,13 @@ public class EffectsHandler {
vao.delete(); vao.delete();
vbo.delete(); vbo.delete();
} }
private void prepFramebufferSize() {
MainWindow window = Minecraft.getInstance().getWindow();
if (framebuffer.framebufferWidth != window.getFramebufferWidth()
|| framebuffer.framebufferHeight != window.getFramebufferHeight()) {
framebuffer.func_216491_a(window.getFramebufferWidth(), window.getFramebufferHeight(),
Minecraft.IS_RUNNING_ON_MAC);
}
}
} }

View file

@ -1,6 +1,5 @@
package com.simibubi.create.foundation.render.backend.effects; package com.simibubi.create.foundation.render.backend.effects;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.util.ArrayList; import java.util.ArrayList;
@ -29,8 +28,6 @@ public class SphereFilterProgram extends GlProgram {
public final GlBuffer effectsUBO; public final GlBuffer effectsUBO;
protected final ArrayList<FilterSphere> filters = new ArrayList<>(16);
protected final int uniformBlock; protected final int uniformBlock;
protected final int uDepth; protected final int uDepth;
@ -82,17 +79,15 @@ public class SphereFilterProgram extends GlProgram {
GL20.glUniform3f(uCameraPos, (float) pos.x, (float) pos.y, (float) pos.z); GL20.glUniform3f(uCameraPos, (float) pos.x, (float) pos.y, (float) pos.z);
} }
public void clear() { public void uploadFilters(ArrayList<FilterSphere> filters) {
filters.clear();
}
public void addSphere(FilterSphere filterSphere) {
filters.add(filterSphere);
}
public void uploadFilters() {
effectsUBO.bind(GL20.GL_ARRAY_BUFFER); effectsUBO.bind(GL20.GL_ARRAY_BUFFER);
effectsUBO.map(GL20.GL_ARRAY_BUFFER, 0, BUFFER_SIZE, this::uploadUBO); effectsUBO.map(GL20.GL_ARRAY_BUFFER, 0, BUFFER_SIZE, buf -> {
buf.putInt(filters.size());
buf.position(16);
FloatBuffer floatBuffer = buf.asFloatBuffer();
filters.forEach(it -> it.write(floatBuffer));
});
effectsUBO.unbind(GL20.GL_ARRAY_BUFFER); effectsUBO.unbind(GL20.GL_ARRAY_BUFFER);
} }
@ -114,14 +109,6 @@ public class SphereFilterProgram extends GlProgram {
GL20.glBindTexture(GL20.GL_TEXTURE_2D, textureObject); GL20.glBindTexture(GL20.GL_TEXTURE_2D, textureObject);
} }
private void uploadUBO(ByteBuffer buf) {
buf.putInt(filters.size());
buf.position(16);
FloatBuffer floatBuffer = buf.asFloatBuffer();
filters.forEach(it -> it.write(floatBuffer));
}
public static class FilterSphere { public static class FilterSphere {
public Vector3d center; public Vector3d center;
public float radius; public float radius;
@ -129,6 +116,7 @@ public class SphereFilterProgram extends GlProgram {
public float fade; public float fade;
public float density = 2; public float density = 2;
public float strength = 1; public float strength = 1;
public boolean blendOver = false;
public Matrix4f filter; public Matrix4f filter;
@ -137,6 +125,11 @@ public class SphereFilterProgram extends GlProgram {
return this; return this;
} }
public FilterSphere setCenter(double x, double y, double z) {
this.center = new Vector3d(x, y, z);
return this;
}
public FilterSphere setRadius(float radius) { public FilterSphere setRadius(float radius) {
this.radius = radius; this.radius = radius;
return this; return this;
@ -167,6 +160,11 @@ public class SphereFilterProgram extends GlProgram {
return this; return this;
} }
public FilterSphere setBlendOver(boolean blendOver) {
this.blendOver = blendOver;
return this;
}
public void write(FloatBuffer buf) { public void write(FloatBuffer buf) {
buf.put(new float[]{ buf.put(new float[]{
(float) center.x, (float) center.x,
@ -176,7 +174,11 @@ public class SphereFilterProgram extends GlProgram {
feather, feather,
fade, fade,
density, density,
strength, blendOver ? 1f : 0f,
1f,
1f,
0f,
0f,
}); });
buf.put(RenderUtil.writeMatrix(filter)); buf.put(RenderUtil.writeMatrix(filter));

View file

@ -16,34 +16,11 @@ uniform vec3 uCameraPos;
struct SphereFilter { struct SphereFilter {
vec4 sphere;// <vec3 position, float radius> vec4 sphere;// <vec3 position, float radius>
vec4 data;// <float feather, float fade, float density, float strength> vec4 d1;// <float feather, float fade, float density, float blend mode>
vec4 d2;// <float surfaceStrength, float bubbleStrength>
mat4 colorOp; mat4 colorOp;
}; };
vec3 getPosition(SphereFilter f) {
return f.sphere.xyz;
}
float getRadius(SphereFilter f) {
return f.sphere.w;
}
float getFeather(SphereFilter f) {
return f.data.x;
}
float getFade(SphereFilter f) {
return f.data.y;
}
float getDensity(SphereFilter f) {
return f.data.z;
}
float getStrength(SphereFilter f) {
return f.data.w;
}
#define N 256 #define N 256
layout (std140) uniform Filters { layout (std140) uniform Filters {
int uCount; int uCount;
@ -113,18 +90,22 @@ float bubbleFilterStrength(vec3 worldDir, float depth, vec4 sphere, float feathe
return clamp(strength, 0., 1.);// * boo; return clamp(strength, 0., 1.);// * boo;
} }
float filterStrength(vec3 worldDir, float depth, vec4 sphere, vec4 data) { float filterStrength(vec3 worldDir, float depth, inout SphereFilter f) {
vec4 sphere = f.sphere;
vec4 data = f.d1;
float feather = data.x; float feather = data.x;
float strength = 0.; float strength = 0.;
// transition effect // transition effect
float transitionRadius = sphere.w + feather; float transitionRadius = sphere.w + feather;
strength += 1. - smoothstep(transitionRadius, transitionRadius + data.y, length(sphere.xyz)); strength += 1. - smoothstep(transitionRadius, transitionRadius + data.y, length(sphere.xyz));
// surface effect
strength += surfaceFilterStrength(worldDir * depth, sphere, feather);
// bubble effect // bubble effect
strength += bubbleFilterStrength(worldDir, depth, sphere, feather, data.z); strength += bubbleFilterStrength(worldDir, depth, sphere, feather, data.z);
strength *= f.d2.y;
// surface effect
strength += surfaceFilterStrength(worldDir * depth, sphere, feather) * f.d2.x;
return strength; return strength;
} }
@ -137,16 +118,16 @@ vec3 applyFilters(vec3 worldDir, float depth, vec3 diffuse) {
for (int i = 0; i < uCount; i++) { for (int i = 0; i < uCount; i++) {
SphereFilter s = uSpheres[i]; SphereFilter s = uSpheres[i];
float strength = filterStrength(worldDir, depth, s.sphere, s.data); float strength = filterStrength(worldDir, depth, s);
if (strength > 0) { if (strength > 0) {
const float fcon = 0.; const float fcon = 0.;
vec3 formatted = mix(diffuse, hsv, fcon); //vec3 formatted = mix(diffuse, hsv, fcon);
vec3 filtered = filterColor(s.colorOp, formatted); vec3 filtered = filterColor(s.colorOp, mix(diffuse, accum, s.d1.w));
filtered = mix(filtered, hsv2rgbWrapped(filtered), fcon); //filtered = mix(filtered, hsv2rgbWrapped(filtered), fcon);
float mixing = clamp(strength * s.data.w, 0., 1.); float mixing = clamp(strength, 0., 1.);
accum = mix(accum, filtered, mixing); accum = mix(accum, filtered, mixing);
} }
} }

View file

@ -1,8 +1,11 @@
#version 140 #version 140
// scaling constants // scaling constants
#define SXY 1.7282818// e - 0.99, this works too well // e - 0.99, this works well, no idea why
#define SZ 1.905// who knows, but it works #define SXY 1.7282818
// 1.90 -> highp close, mediump far
// 1.91 -> mediump close, highp far
#define SZ 1.905
in vec4 aVertex;// <vec2 position, vec2 texCoords> in vec4 aVertex;// <vec2 position, vec2 texCoords>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 3 KiB