From 83dc241cd215a4fed8b7bcf0c1d63823eef26cdc Mon Sep 17 00:00:00 2001 From: JozsefA Date: Sat, 17 Apr 2021 13:04:42 -0700 Subject: [PATCH] Basic spherical effect --- .../render/backend/effects/ColorMatrices.java | 12 ++- .../backend/effects/EffectsHandler.java | 28 +++++-- .../backend/effects/SphereFilterProgram.java | 20 ++++- .../create/flywheel/shaders/area_effect.frag | 74 +++++++++++++++---- 4 files changed, 108 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/effects/ColorMatrices.java b/src/main/java/com/simibubi/create/foundation/render/backend/effects/ColorMatrices.java index ab32b6b97..db3097b21 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/effects/ColorMatrices.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/effects/ColorMatrices.java @@ -59,7 +59,7 @@ public class ColorMatrices { } // https://stackoverflow.com/a/8510751 - public static Matrix4f hueShift(float rot) { + public static Matrix4f hueShiftRGB(float rot) { Matrix4f mat = new Matrix4f(); mat.loadIdentity(); @@ -78,4 +78,14 @@ public class ColorMatrices { return mat; } + + public static Matrix4f hueShiftHSV(float rot) { + Matrix4f mat = new Matrix4f(); + + mat.loadIdentity(); + + //mat.a03 = 0.5f; + + return mat; + } } 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 79d71205f..d3f7f4e06 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 @@ -106,18 +106,30 @@ public class EffectsHandler { inverseView.invert(); program.bindInverseView(inverseView); - Vector3d pos1 = new Vector3d(330, 0, 110); + Vector3d pos1 = new Vector3d(852, 79, -204); Vector3d cameraPos = gameRenderer.getActiveRenderInfo().getProjectedView(); program.setCameraPos(cameraPos.inverse()); - for (int i = 0; i < 16; i++) { - program.addSphere(new SphereFilterProgram.FilterSphere() - .setCenter(pos1.subtract(cameraPos).add(0, 0, i * 10)) - .setRadius(15) - .setFeather(0f) - .setFilter(ColorMatrices.hueShift((float) i / 16 * 360 + AnimationTickHolder.getRenderTime()))); - } +// int n = 20; +// double rad = 15; +// for (int i = 0; i < n; i++) { +// double angle = ((double) i) / n * Math.PI * 2; +// program.addSphere(new SphereFilterProgram.FilterSphere() +// .setCenter(pos1.subtract(cameraPos).add(Math.sin(angle) * rad, 0, Math.cos(angle) * rad)) +// .setRadius(10) +// .setFeather(0f) +// .setFilter(ColorMatrices.hueShiftRGB((float) i / n * 360 + i / 2f))); +// } + + Matrix4f filter = ColorMatrices.sepia(1f); + + program.addSphere(new SphereFilterProgram.FilterSphere() + .setCenter(pos1.subtract(cameraPos)) + .setRadius(40) + .setFeather(20f) + .setHsv(false) + .setFilter(filter)); program.uploadFilters(); 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 dfa0c397d..5492c0b42 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 @@ -20,7 +20,7 @@ public class SphereFilterProgram extends GlProgram { protected static final int UBO_BINDING = 4; protected static final int SPHERE_FILTER_SIZE = 24 * 4; // - protected static final int MAX_FILTERS = 16; // arbitrary + protected static final int MAX_FILTERS = 256; // arbitrary protected static final int EXTRA_INFO = 16; // array length: int + padding protected static final int ALL_FILTERS_SIZE = MAX_FILTERS * SPHERE_FILTER_SIZE; @@ -126,6 +126,8 @@ public class SphereFilterProgram extends GlProgram { public Vector3d center; public float radius; public float feather; + public float strength = 1; + public boolean hsv; public Matrix4f filter; @@ -144,6 +146,16 @@ public class SphereFilterProgram extends GlProgram { return this; } + public FilterSphere setStrength(float strength) { + this.strength = strength; + return this; + } + + public FilterSphere setHsv(boolean hsv) { + this.hsv = hsv; + return this; + } + public FilterSphere setFilter(Matrix4f filter) { this.filter = filter; return this; @@ -156,9 +168,9 @@ public class SphereFilterProgram extends GlProgram { (float) center.z, radius, feather, - 0, // padding, we could add more parameters here - 0, - 0 + strength, + hsv ? 1f : 0f, + 0 // padding, we could add more parameters here }); 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 1e06411d8..005fe91f8 100644 --- a/src/main/resources/assets/create/flywheel/shaders/area_effect.frag +++ b/src/main/resources/assets/create/flywheel/shaders/area_effect.frag @@ -16,11 +16,11 @@ uniform vec3 uCameraPos; struct SphereFilter { vec4 sphere;// - float feather; + vec3 data;// mat4 colorOp; }; -#define N 16 +#define N 256 layout (std140) uniform Filters { int uCount; SphereFilter uSpheres[N]; @@ -31,11 +31,11 @@ float linearizeDepth(float d, float zNear, float zFar) { return zNear * zFar / (zFar + zNear - clipZ * (zFar - zNear)); } -vec4 filterColor(mat4 colorOp, vec4 frag) { +vec3 filterColor(mat4 colorOp, vec3 color) { // preserve alpha while transforming color - vec4 i = vec4(frag.rgb, 1.); + vec4 i = vec4(color, 1.); i *= colorOp; - return vec4(i.rgb, frag.a); + return i.rgb; } float getDepth() { @@ -44,16 +44,65 @@ float getDepth() { return linearizeDepth(depth, uNearPlane, uFarPlane); } -vec4 applyFilters(vec3 worldPos, vec4 diffuse) { - vec4 accum = diffuse; +float overlayFilterAmount(in vec3 worldPos, in vec4 sphere, in float feather) { + float distance = distance(sphere.xyz, worldPos); + return 1 - smoothstep(sphere.w, sphere.w + feather, distance); +} + +float sphereFilterAmount(in vec3 worldDir, in float depth, in vec4 sphere, in float feather) { + float feathering = 1 - smoothstep(sphere.w, sphere.w + feather, length(sphere.xyz)); + feathering += overlayFilterAmount(worldDir * depth, sphere, feather); + vec3 oc = -sphere.xyz; + + float rayLengthSqr = dot(worldDir, worldDir); + float b = 2.0 * dot(-sphere.xyz, worldDir); + float sphereDistSqr = dot(sphere.xyz, sphere.xyz); + float b2 = b*b; + float d = 4. * rayLengthSqr; + float e = 1. / (2.0*rayLengthSqr); + + float radius = sphere.w; + float c = sphereDistSqr - radius*radius; + float discriminant = b2 - d * c; + float hitDepth = (-b - sqrt(discriminant)) * e; + + + if (discriminant > 0 && hitDepth > 0 && hitDepth < depth) { + // float c = sphereDistSqr - sphere.w*sphere.w; + // float discriminant = b2 - d * c; + // float hitDepth = (-b - sqrt(discriminant)) * e; + + vec3 hitPos = worldDir * hitDepth; + + vec3 normal = normalize(hitPos - sphere.xyz); + + return feathering - dot(normal, normalize(worldDir)) * 1.3 - 0.1; + } else { + return feathering; + } +} + +vec3 applyFilters(in vec3 worldDir, in float depth, in vec3 diffuse) { + vec3 worldPos = worldDir * depth; + + vec3 accum = diffuse; + vec3 diffuseHSV = rgb2hsv(accum); for (int i = 0; i < uCount; i++) { SphereFilter s = uSpheres[i]; - float distance = distance(s.sphere.xyz, worldPos); - float strength = 1 - smoothstep(s.sphere.w - s.feather, s.sphere.w + s.feather, distance); + //float strength = overlayFilterAmount(worldPos, s.sphere, s.data.x); + float strength = sphereFilterAmount(worldDir, depth, s.sphere, s.data.x); - accum = mix(accum, filterColor(s.colorOp, diffuse), strength); + //accum = vec3(strength, strength, strength); + + vec3 toFilter = mix(diffuse, diffuseHSV, s.data.z); + + vec3 filtered = filterColor(s.colorOp, diffuse); + + filtered = mix(filtered, hsv2rgbWrapped(filtered), s.data.z); + + accum = mix(accum, filtered, clamp(strength * s.data.y, 0., 1.)); } return accum; @@ -69,10 +118,9 @@ vec4 debugGrid(vec3 worldPos, vec4 diffuse) { void main() { float depth = getDepth(); - vec3 worldPos = WorldDir * depth; vec4 diffuse = texture2D(uColor, ScreenCoord); - Color = applyFilters(worldPos, diffuse); - //Color = debugGrid(worldPos, diffuse); + Color = vec4(applyFilters(WorldDir, depth, diffuse.rgb), diffuse.a); + //Color = debugGrid(WorldDir * depth, Color); }