Basic spherical effect

This commit is contained in:
JozsefA 2021-04-17 13:04:42 -07:00
parent fafd7c84be
commit 83dc241cd2
4 changed files with 108 additions and 26 deletions

View file

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

View file

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

View file

@ -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; // <vec4, float + padding, mat4>
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));

View file

@ -16,11 +16,11 @@ uniform vec3 uCameraPos;
struct SphereFilter {
vec4 sphere;// <vec3 position, float radius>
float feather;
vec3 data;// <float feather, float strength, float hsv marker>
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);
}