diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorScreen.java b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorScreen.java index e7074cb6d..ed898a196 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorScreen.java +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorScreen.java @@ -52,7 +52,8 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen { } private static Integer step(ScrollValueBehaviour.StepContext ctx, int base) { - return ctx.control ? 1 : base * (ctx.shift ? 5 : 1); + if (ctx.control) return 1; + return base * (ctx.shift ? 5 : 1) - ctx.currentValue % base; } @Override @@ -71,30 +72,36 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen { confirmButton = new IconButton(guiLeft + background.width - 33, guiTop + background.height - 24, AllIcons.I_CONFIRM); widgets.add(confirmButton); - radius = new ScrollInput(guiLeft + 46, guiTop + 117, 28, 18) + + int xRight = guiLeft + 53; + int xLeft = guiLeft + 93; + int yTop = guiTop + 117; + int yBottom = guiTop + 139; + + radius = new ScrollInput(xRight, yTop, 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) + feather = new ScrollInput(xRight, yBottom, 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) + .setState((int) (tile.feather * 10)); + density = new ScrollInput(xLeft, yTop, 28, 18) .titled(new StringTextComponent("Density")) .withStepFunction(ctx -> step(ctx, 10)) .calling(tile::setDensity) .withRange(0, 401) .setState((int) (tile.density * 100)); + fade = new ScrollInput(xLeft, yBottom, 28, 18) + .titled(new StringTextComponent("Fade")) + .withStepFunction(ctx -> step(ctx, 1)) + .calling(tile::setFade) + .withRange(0, 51) + .setState((int) (tile.fade * 10)); Collections.addAll(widgets, radius, density, feather, fade); } @@ -107,17 +114,17 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen { Vector rowInputs = inputs.get(row); rowInputs.forEach(widgets::remove); rowInputs.clear(); - int index = row; - FilterStep instruction = stages.get(row); + FilterStep filter = stages.get(row); ScrollInput type = - new SelectionScrollInput(x, y + rowHeight * row, 86, 18).forOptions(ColorEffects.getOptions()) - .calling(state -> instructionUpdated(index, state)) - .setState(instruction.filter.ordinal()) + new SelectionScrollInput(x, y + rowHeight * row, 86, 18) + .forOptions(ColorEffect.getOptions()) + .calling(state -> instructionUpdated(row, state)) + .setState(filter.filter.id) .titled(Lang.translate("gui.chromatic_projector.filter")); ScrollInput value = new ScrollInput(x + 86 + 2, y + rowHeight * row, 28, 18) - .calling(state -> instruction.value = state); + .calling(state -> filter.value = state); rowInputs.add(type); rowInputs.add(value); @@ -129,7 +136,7 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen { public void updateParamsOfRow(int row) { FilterStep instruction = stages.get(row); Vector rowInputs = inputs.get(row); - ColorEffects def = instruction.filter; + ColorEffect def = instruction.filter; boolean hasValue = def.hasParameter; ScrollInput value = rowInputs.get(1); @@ -137,11 +144,10 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen { if (hasValue) value.withRange(def.minValue, def.maxValue + 1) //.titled(Lang.translate(def.parameterKey)) - .withShiftStep(5) .setState(instruction.value) .onChanged(); - value.withStepFunction(value.standardStep()); + value.withStepFunction(def.step()); } @Override @@ -158,10 +164,10 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen { } FilterStep step = stages.get(row); - ColorEffects def = step.filter; + ColorEffect def = step.filter; def.background.draw(matrixStack, guiLeft, guiTop + 14 + yOffset); - if (def != ColorEffects.END) + if (def != ColorEffect.END) label(matrixStack, 36, yOffset - 3, Lang.translate(def.translationKey)); if (def.hasParameter) { String text = step.filter.formatValue(step.value); @@ -172,7 +178,7 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen { renderScroll(matrixStack, radius, 2f); renderScroll(matrixStack, density, 100f); - renderScroll(matrixStack, feather, 4f); + renderScroll(matrixStack, feather, 10f); renderScroll(matrixStack, fade, 10f); textRenderer.drawWithShadow(matrixStack, title, guiLeft - 3 + (background.width - textRenderer.getWidth(title)) / 2, guiTop + 3, @@ -206,11 +212,11 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen { } private void instructionUpdated(int index, int state) { - ColorEffects newValue = ColorEffects.values()[state]; + ColorEffect newValue = ColorEffect.all.get(state); stages.get(index).filter = newValue; - stages.get(index).value = 100; + stages.get(index).value = newValue.defaultValue; updateParamsOfRow(index); - if (newValue == ColorEffects.END) { + if (newValue == ColorEffect.END) { for (int i = stages.size() - 1; i > index; i--) { stages.remove(i); Vector rowInputs = inputs.get(i); @@ -219,7 +225,7 @@ public class ChromaticProjectorScreen extends AbstractSimiScreen { } } else { if (index + 1 < stages.capacity() && index + 1 == stages.size()) { - stages.add(new FilterStep(ColorEffects.END)); + stages.add(new FilterStep(ColorEffect.END)); initInputsOfRow(index + 1); } } diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorTileEntity.java index b6f9f4089..d2ebe9f6f 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorTileEntity.java +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorTileEntity.java @@ -2,7 +2,7 @@ package com.simibubi.create.content.curiosities.projector; import java.util.Vector; -import com.simibubi.create.foundation.render.backend.effects.SphereFilterProgram; +import com.simibubi.create.foundation.render.backend.effects.FilterSphere; import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; import net.minecraft.tileentity.TileEntity; @@ -24,17 +24,17 @@ public class ChromaticProjectorTileEntity extends TileEntity implements IInstanc super(te); } - public SphereFilterProgram.FilterSphere makeFilter() { + public FilterSphere makeFilter() { Matrix4f filter = FilterStep.fold(stages); BlockPos pos = getPos(); - return new SphereFilterProgram.FilterSphere() + return new FilterSphere() .setFilter(filter) .setCenter(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5) .setRadius(radius) .setDensity(density) .setFeather(feather) - .setBlendOver(false) + .setBlendOver(true) .setFade(fade); } @@ -49,12 +49,12 @@ public class ChromaticProjectorTileEntity extends TileEntity implements IInstanc } public ChromaticProjectorTileEntity setFeather(int feather) { - this.feather = feather / 4f; + this.feather = feather / 10f; return this; } public ChromaticProjectorTileEntity setFade(int fade) { - this.fade = feather / 10f; + this.fade = fade / 10f; return this; } diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffect.java b/src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffect.java new file mode 100644 index 000000000..12c0a0822 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffect.java @@ -0,0 +1,112 @@ +package com.simibubi.create.content.curiosities.projector; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.render.backend.effects.ColorMatrices; +import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.text.ITextComponent; + +public class ColorEffect { + static final ArrayList all = new ArrayList<>(); + static final HashMap lookup = new HashMap<>(); + private static int nextId = 0; + + public static final ColorEffect INVERT = create("invert", ColorMatrices::invert); + public static final ColorEffect SEPIA = create("sepia", ColorMatrices::sepia); + public static final ColorEffect GRAYSCALE = create("grayscale", ColorMatrices::grayscale); + public static final ColorEffect DARKEN = create("darken", ColorMatrices::darken).setDefaultValue(20); + public static final ColorEffect SATURATE = create("saturate", ColorMatrices::saturate).setRange(0, 200); + public static final ColorEffect HUE_SHIFT = create("hue_shift", ColorMatrices::hueShift).setRange(0, 360).setDivisor(1f).setDefaultValue(120); + public static final ColorEffect END = create("end", ColorMatrices::identity).setBackground(AllGuiTextures.PROJECTOR_END); + + boolean hasParameter; + AllGuiTextures background; + + int defaultValue = 100; + int minValue = 0; + int maxValue = 100; + float divisor = 100f; + + final int id; + final FilterFactory filter; + final String name; + final String translationKey; + + public ColorEffect(String name, FilterFactory filter) { + this.filter = filter; + this.name = name; + this.translationKey = "gui.chromatic_projector.filter." + Lang.asId(name); + this.id = nextId++; + + lookup.put(name, this); + all.add(this); + } + + public ColorEffect setHasParameter(boolean hasParameter) { + this.hasParameter = hasParameter; + return setBackground(hasParameter ? AllGuiTextures.PROJECTOR_FILTER_STRENGTH : AllGuiTextures.PROJECTOR_FILTER); + } + + public ColorEffect setBackground(AllGuiTextures background) { + this.background = background; + return this; + } + + public ColorEffect setDefaultValue(int defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + public ColorEffect setRange(int minValue, int maxValue) { + this.minValue = minValue; + this.maxValue = maxValue; + return this; + } + + public ColorEffect setDivisor(float divisor) { + this.divisor = divisor; + return this; + } + + public Function step() { + return c -> { + if (c.control) return 1; + if (c.shift) return 20; + return 5; + }; + } + + String formatValue(int value) { + if (this == HUE_SHIFT) + return value + Lang.translate("generic.unit.degrees").getString(); + return "" + value; + } + + static List getOptions() { + List options = new ArrayList<>(); + for (ColorEffect entry : all) + options.add(Lang.translate(entry.translationKey)); + return options; + } + + @FunctionalInterface + public interface FilterFactory { + Matrix4f create(float param); + } + + public static ColorEffect create(String name, Supplier filter) { + return new ColorEffect(name, $ -> filter.get()).setHasParameter(false); + } + + public static ColorEffect create(String name, FilterFactory filter) { + return new ColorEffect(name, filter).setHasParameter(true); + } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffects.java b/src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffects.java deleted file mode 100644 index 964af44d0..000000000 --- a/src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffects.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.simibubi.create.content.curiosities.projector; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -import com.simibubi.create.foundation.gui.AllGuiTextures; -import com.simibubi.create.foundation.render.backend.effects.ColorMatrices; -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.text.ITextComponent; - -public enum ColorEffects { - INVERT(ColorMatrices::invert), - SEPIA(ColorMatrices::sepia), - GRAYSCALE(ColorMatrices::grayscale), - DARKEN(ColorMatrices::darken), - SATURATE(ColorMatrices::saturate, 0, 200), - HUE_SHIFT(ColorMatrices::hueShift, 0, 360, 1f), - END(ColorMatrices::identity, AllGuiTextures.PROJECTOR_END), - - ; - - FilterFactory filter; - boolean hasParameter; - String translationKey; - AllGuiTextures background; - - int minValue = 0; - int maxValue = 100; - float divisor = 100f; - - ColorEffects(Supplier filter, AllGuiTextures background) { - this($ -> filter.get(), false, background); - } - - ColorEffects(Supplier filter) { - this($ -> filter.get(), false, AllGuiTextures.PROJECTOR_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.minValue = minValue; - this.maxValue = maxValue; - this.divisor = divisor; - } - - ColorEffects(FilterFactory filter, boolean hasParameter, AllGuiTextures background) { - this.filter = filter; - this.hasParameter = hasParameter; - this.background = background; - 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 getOptions() { - List options = new ArrayList<>(); - for (ColorEffects entry : values()) - options.add(Lang.translate(entry.translationKey)); - return options; - } - - @FunctionalInterface - public interface FilterFactory { - Matrix4f create(float param); - } -} diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/FilterStep.java b/src/main/java/com/simibubi/create/content/curiosities/projector/FilterStep.java index cb77ed07e..e2c900236 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/projector/FilterStep.java +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/FilterStep.java @@ -9,14 +9,14 @@ import net.minecraft.util.math.vector.Matrix4f; public class FilterStep { - ColorEffects filter; + ColorEffect filter; int value; - public FilterStep(ColorEffects filter) { + public FilterStep(ColorEffect filter) { this.filter = filter; } - public FilterStep(ColorEffects filter, int value) { + public FilterStep(ColorEffect filter, int value) { this.filter = filter; this.value = value; } @@ -26,7 +26,7 @@ public class FilterStep { } public static Matrix4f fold(Vector filters) { - Iterator stepIterator = filters.stream().filter(it -> it != null && it.filter != ColorEffects.END).iterator(); + Iterator stepIterator = filters.stream().filter(it -> it != null && it.filter != ColorEffect.END).iterator(); if (stepIterator.hasNext()) { Matrix4f accum = stepIterator.next().createFilter(); @@ -41,8 +41,8 @@ public class FilterStep { public static Vector createDefault() { Vector instructions = new Vector<>(ChromaticProjectorScreen.MAX_STEPS); - instructions.add(new FilterStep(ColorEffects.SEPIA, 100)); - instructions.add(new FilterStep(ColorEffects.END)); + instructions.add(new FilterStep(ColorEffect.SEPIA, 100)); + instructions.add(new FilterStep(ColorEffect.END)); return instructions; } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/effects/EffectsHandler.java b/src/main/java/com/simibubi/create/foundation/render/backend/effects/EffectsHandler.java index f6368c9b5..24e95175c 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/effects/EffectsHandler.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/effects/EffectsHandler.java @@ -51,7 +51,7 @@ public class EffectsHandler { private final GlBuffer vbo = new GlBuffer(GL20.GL_ARRAY_BUFFER); - private final ArrayList spheres; + private final ArrayList spheres; public EffectsHandler() { spheres = new ArrayList<>(); @@ -74,7 +74,7 @@ public class EffectsHandler { } - public void addSphere(SphereFilterProgram.FilterSphere sphere) { + public void addSphere(FilterSphere sphere) { this.spheres.add(sphere); } @@ -115,7 +115,7 @@ public class EffectsHandler { program.setCameraPos(cameraPos.inverse()); - for (SphereFilterProgram.FilterSphere sphere : spheres) { + for (FilterSphere sphere : spheres) { sphere.center = sphere.center.subtract(cameraPos); } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/effects/FilterSphere.java b/src/main/java/com/simibubi/create/foundation/render/backend/effects/FilterSphere.java new file mode 100644 index 000000000..77aa77123 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/effects/FilterSphere.java @@ -0,0 +1,93 @@ +package com.simibubi.create.foundation.render.backend.effects; + +import java.nio.FloatBuffer; + +import com.simibubi.create.foundation.render.backend.RenderUtil; + +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Vector3d; + +public class FilterSphere { + public Vector3d center; + public float radius; + public float feather; + public float fade; + public float density = 2; + public float strength = 1; + public boolean blendOver = false; + + public float r; + public float g; + public float b; + public float colorFeather; + + public Matrix4f filter; + + public FilterSphere setCenter(Vector3d center) { + this.center = center; + 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) { + this.radius = radius; + return this; + } + + public FilterSphere setFeather(float feather) { + this.feather = feather; + return this; + } + + public FilterSphere setFade(float fade) { + this.fade = fade; + return this; + } + + public FilterSphere setDensity(float density) { + this.density = density; + return this; + } + + public FilterSphere setStrength(float strength) { + this.strength = strength; + return this; + } + + public FilterSphere setFilter(Matrix4f filter) { + this.filter = filter; + return this; + } + + public FilterSphere setBlendOver(boolean blendOver) { + this.blendOver = blendOver; + return this; + } + + public void write(FloatBuffer buf) { + buf.put(new float[]{ + (float) center.x, + (float) center.y, + (float) center.z, + radius, + feather, + fade, + density, + blendOver ? 1f : 0f, + 1f, + 1f, + 0f, + 0f, + 0.5f, //r, + 0.1f, //g, + 0.1f, //b, + 0.12f, //colorFeather, + }); + + buf.put(RenderUtil.writeMatrix(filter)); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/effects/SphereFilterProgram.java b/src/main/java/com/simibubi/create/foundation/render/backend/effects/SphereFilterProgram.java index 406059e74..229aa2f5c 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/effects/SphereFilterProgram.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/effects/SphereFilterProgram.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL31; -import com.simibubi.create.foundation.render.backend.RenderUtil; import com.simibubi.create.foundation.render.backend.gl.GlBuffer; import com.simibubi.create.foundation.render.backend.gl.shader.GlProgram; @@ -109,79 +108,4 @@ public class SphereFilterProgram extends GlProgram { GL20.glBindTexture(GL20.GL_TEXTURE_2D, textureObject); } - public static class FilterSphere { - public Vector3d center; - public float radius; - public float feather; - public float fade; - public float density = 2; - public float strength = 1; - public boolean blendOver = false; - - public Matrix4f filter; - - public FilterSphere setCenter(Vector3d center) { - this.center = center; - 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) { - this.radius = radius; - return this; - } - - public FilterSphere setFeather(float feather) { - this.feather = feather; - return this; - } - - public FilterSphere setFade(float fade) { - this.fade = fade; - return this; - } - - public FilterSphere setDensity(float density) { - this.density = density; - return this; - } - - public FilterSphere setStrength(float strength) { - this.strength = strength; - return this; - } - - public FilterSphere setFilter(Matrix4f filter) { - this.filter = filter; - return this; - } - - public FilterSphere setBlendOver(boolean blendOver) { - this.blendOver = blendOver; - return this; - } - - public void write(FloatBuffer buf) { - buf.put(new float[]{ - (float) center.x, - (float) center.y, - (float) center.z, - radius, - feather, - fade, - density, - blendOver ? 1f : 0f, - 1f, - 1f, - 0f, - 0f, - }); - - buf.put(RenderUtil.writeMatrix(filter)); - } - } } diff --git a/src/main/resources/assets/create/flywheel/shaders/area_effect.frag b/src/main/resources/assets/create/flywheel/shaders/area_effect.frag index e36d9056d..3a43ac7a4 100644 --- a/src/main/resources/assets/create/flywheel/shaders/area_effect.frag +++ b/src/main/resources/assets/create/flywheel/shaders/area_effect.frag @@ -18,6 +18,7 @@ struct SphereFilter { vec4 sphere;// vec4 d1;// vec4 d2;// + vec4 colorMask;// mat4 colorOp; }; @@ -112,7 +113,6 @@ float filterStrength(vec3 worldDir, float depth, inout SphereFilter f) { vec3 applyFilters(vec3 worldDir, float depth, vec3 diffuse) { vec3 worldPos = worldDir * depth; - vec3 hsv = rgb2hsv(diffuse); vec3 accum = vec3(diffuse); for (int i = 0; i < uCount; i++) { @@ -123,12 +123,18 @@ vec3 applyFilters(vec3 worldDir, float depth, vec3 diffuse) { if (strength > 0) { const float fcon = 0.; - //vec3 formatted = mix(diffuse, hsv, fcon); - vec3 filtered = filterColor(s.colorOp, mix(diffuse, accum, s.d1.w)); - //filtered = mix(filtered, hsv2rgbWrapped(filtered), fcon); + vec3 baseColor = mix(diffuse, accum, s.d1.w); + vec3 filtered = filterColor(s.colorOp, baseColor); + + vec3 baseHsv = rgb2hsv(baseColor); + vec3 maskHsv = rgb2hsv(s.colorMask.rgb); + vec3 diff = abs(baseHsv - maskHsv) * vec3(1., 1.1, 0.1); + float colorMask = step(s.colorMask.w, length(diff)); float mixing = clamp(strength, 0., 1.); - accum = mix(accum, filtered, mixing); + + accum = mix(accum, filtered, mixing * colorMask); + //accum = vec3(colorMask); } } diff --git a/src/main/resources/assets/create/textures/gui/projector.png b/src/main/resources/assets/create/textures/gui/projector.png index 165ac24d2..968618e94 100644 Binary files a/src/main/resources/assets/create/textures/gui/projector.png and b/src/main/resources/assets/create/textures/gui/projector.png differ