More polish

- UI icons
 - Color masking
 - Better scroll ux
 - FilterSphere now has its own file
This commit is contained in:
JozsefA 2021-04-23 14:38:31 -07:00
parent 3879d55517
commit e8ab21c184
10 changed files with 264 additions and 204 deletions

View file

@ -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<ScrollInput> 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<ScrollInput> 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<ScrollInput> 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);
}
}

View file

@ -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;
}

View file

@ -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<ColorEffect> all = new ArrayList<>();
static final HashMap<String, ColorEffect> 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<ScrollValueBehaviour.StepContext, Integer> 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<ITextComponent> getOptions() {
List<ITextComponent> 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<Matrix4f> filter) {
return new ColorEffect(name, $ -> filter.get()).setHasParameter(false);
}
public static ColorEffect create(String name, FilterFactory filter) {
return new ColorEffect(name, filter).setHasParameter(true);
}
}

View file

@ -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<Matrix4f> filter, AllGuiTextures background) {
this($ -> filter.get(), false, background);
}
ColorEffects(Supplier<Matrix4f> 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<ITextComponent> getOptions() {
List<ITextComponent> options = new ArrayList<>();
for (ColorEffects entry : values())
options.add(Lang.translate(entry.translationKey));
return options;
}
@FunctionalInterface
public interface FilterFactory {
Matrix4f create(float param);
}
}

View file

@ -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<FilterStep> filters) {
Iterator<FilterStep> stepIterator = filters.stream().filter(it -> it != null && it.filter != ColorEffects.END).iterator();
Iterator<FilterStep> 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<FilterStep> createDefault() {
Vector<FilterStep> 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;
}
}

View file

@ -51,7 +51,7 @@ public class EffectsHandler {
private final GlBuffer vbo = new GlBuffer(GL20.GL_ARRAY_BUFFER);
private final ArrayList<SphereFilterProgram.FilterSphere> spheres;
private final ArrayList<FilterSphere> 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);
}

View file

@ -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));
}
}

View file

@ -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));
}
}
}

View file

@ -18,6 +18,7 @@ struct SphereFilter {
vec4 sphere;// <vec3 position, float radius>
vec4 d1;// <float feather, float fade, float density, float blend mode>
vec4 d2;// <float surfaceStrength, float bubbleStrength>
vec4 colorMask;// <vec3 rgb, float feather>
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);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB