From e8ab21c184d5fe1de04493dbb986f868253e8511 Mon Sep 17 00:00:00 2001 From: JozsefA Date: Fri, 23 Apr 2021 14:38:31 -0700 Subject: [PATCH] More polish - UI icons - Color masking - Better scroll ux - FilterSphere now has its own file --- .../projector/ChromaticProjectorScreen.java | 60 +++++----- .../ChromaticProjectorTileEntity.java | 12 +- .../curiosities/projector/ColorEffect.java | 112 ++++++++++++++++++ .../curiosities/projector/ColorEffects.java | 81 ------------- .../curiosities/projector/FilterStep.java | 12 +- .../backend/effects/EffectsHandler.java | 6 +- .../render/backend/effects/FilterSphere.java | 93 +++++++++++++++ .../backend/effects/SphereFilterProgram.java | 76 ------------ .../create/flywheel/shaders/area_effect.frag | 16 ++- .../assets/create/textures/gui/projector.png | Bin 3086 -> 3428 bytes 10 files changed, 264 insertions(+), 204 deletions(-) create mode 100644 src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffect.java delete mode 100644 src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffects.java create mode 100644 src/main/java/com/simibubi/create/foundation/render/backend/effects/FilterSphere.java 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 165ac24d206aa6a5ded0317397fded44b7030006..968618e948b3dde383ab64f20f199f5166f4d068 100644 GIT binary patch literal 3428 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 literal 3086 zcmcImdpwlc8$a)B7(*&1mrBtjid@p#%E$~6BbSoaB{OX3HWhNqWX8A@ev-^=rHeNKn3< z7Mh_S_#1NvD)5|diMh7zj>K$%4<5-Qsu zv88)?aX27Ca{rIUyFGo~S6tCQkwGguDjd4ku;CcbyXd{Uvz@pzN08E zM;CuG3U}TPB3!@wYFq=wHXg&7or)eqfo*%bT3W2tRWkyjNf90``2^G0n&~KsD2HHz z;pe5u^F86!s@^_6Q*+yo`ky`P(jHqUrpHV-Zh<-rSm5el;jKMk4Wrnzat|jXCIdjY zhZE@gddzTYPgB=_biNp5HK}&PFaScBfgcpy;cu+9EsK;GE|FqO4E5uEKRUJBqT%^ zN&CoJKQ$)#aj*RF+-Fu%$;@ZEek`%7;RZ5_IG0(FznrzG3v~{jH4uLIaJ$1mA=VK@ zwmAV3%Q3r%rAHcJ*K@0lsZ^>@3swaObsoV(R~V?`^DJ*v_Twi{ip;rspsrqm^7Z@u z#?XoUDH<~Xaju|!xL41ch?|>4I4C@Cp__f%LgrYlp^Nho9e~SIQL9zez&-Z^09oF= z_IVZ3@2)x}_s{ zuWJ}CP~Xk6{8fEEzvZ$H!TOWC{c*Q=#6#$~rVh@xrvLUjG(A0?1TH_qn&Cu~5%ak< zZ;p-s!4T?@<2Ji%`{}Uz+Cn)ArF_+G`as82SYx?THY5(=)812gD~3N9$|-2K z2DNZf3W|AeSV>!!`j18-c8;L`aodgMwEdaR&rMP z(H4ziuCu$e5}C_=MCl6BsEw(G3sy$L`va}G;qv=QW2h^Rp)qu4hG%1(tocqR$iB6x z$J~7l;A~;yk={8-u)ciH%jwo|I3!wocw!+ZE_1ONhX4rXtxay~v!cimk6c&d56?ks zu1lA|u2r#{&}cL_&(kOa96VBp3JJe&>ZXy`6vdb@Ub{l!oj7u^NqnA%4WWk~wU&z9 zyix1ykclXL@*Ja(%C7`%%gZmqGGB{`4iBjiYvA2{53|73jWL_g7NarXNLw$ab97eE zrPaqEhYDry*yx93A;Y4GbcPxe|G`sIDSxYM&Dv{+>?>{2d!Z7fRyjsy7RgE*^ni@7 z@LKrdxKH;DL!6-qZ;6!Y#>b_6Zf*M$doI3AksNpE>MvCAvh40#ianQR%#_GTKh%R6 z?#H8N?~6vLG31SCOAjnjk!^6L^>MZNZ`eZhDM5x8HhUm8(J_r8$+Pj z8M+)6CkdQ(ZUL_A{JY=aq1Z6-xz&Vy?q@q*cbG&krKfM|mH%^;C`cxh{~S2Ui2yWb zf6eI)kVbC6rwN(A7rt#-&kLxeeK5rEw^m|^y~*Kqi z@|-nV3@$qxFrWJi&vL2^BHB>Guru3De6(=T4|o1@7?&Gv*${m(IHvWB6;AG6PS2M1}Qu)mDjA{+AB?CCU%X`1cO+R%AyRQffI$&ovL?oH! zZ$8O+)l~G)st1cnCe|jQ2fWBRmKo!Mdi|8uv|d6d>#c6 z$ci^y1!CHL+oUEsct3B5lo>#+_!;y6rH8tD3 zZ$!A(p1m8^?{d)H!OmQahSr$9*qf!P+GO4i65}M}43{$~+JrE!T}1ScjEWkZm=JU? zr{wGkrtMj&-<%tR1&@wF$Q4Omc0FPT!;5`2VME8c=}Sv=Zwe)H;-s082Jm>o;}Kdr zBx7UFWU#Qrb7IBp!uBf7#LEL4FEaW1D#Bt>ax!vmlURxNd^toK%_z@k+Y0EXmKc7C zE~nE1AmTx!#o`M-l{oDM1l4J2DqWqOTj>`ypjgB%HpCKws}uvh8*l<$4e*UVK{{F= zcFhm9k-*sg6HchD4A$)!9ngthT9}=eY=_4uztugx-esyE6=flHDD~r6Pt%2BN08~w z_^B>$v97L8#OveIk0w5YTpt0>lSPy%_g%}t(>QssGrHUE#8mfln3*+bV8!m!pr8`5 zCi+}OcHb^F5dVB&E*(MTKQ$_J03H=Qo+%!WPwOGD`%DoYD(dTIy