From 899b8b1e7a5230e5c684d4dae084c68ac5a0a5e6 Mon Sep 17 00:00:00 2001 From: Edwin Jakobs Date: Sun, 1 Mar 2020 13:06:47 +0100 Subject: [PATCH] Add PerspectivePlane distortion filter --- orx-fx/README.md | 1 + orx-fx/src/main/kotlin/distort/Raycast.kt | 60 +++++++++++++++++++ .../fx/gl3/distort/perspective-plane.frag | 46 ++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 orx-fx/src/main/kotlin/distort/Raycast.kt create mode 100644 orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/distort/perspective-plane.frag diff --git a/orx-fx/README.md b/orx-fx/README.md index 340d8986..3063b3dd 100644 --- a/orx-fx/README.md +++ b/orx-fx/README.md @@ -70,6 +70,7 @@ All distortion effects are opacity preserving - `StackRepeat` - repeats the source input in a stack fashion - `HorizontalWave` - applies a horizontal wave effect on the source input - `VerticalWave` - applies a vertical wave effect on the source input + - `PerspectivePlane` - applies a planar perspective distortion on the source input ### Dither - `ADither` - a selection of dithering effects diff --git a/orx-fx/src/main/kotlin/distort/Raycast.kt b/orx-fx/src/main/kotlin/distort/Raycast.kt new file mode 100644 index 00000000..212cb0d1 --- /dev/null +++ b/orx-fx/src/main/kotlin/distort/Raycast.kt @@ -0,0 +1,60 @@ +package org.openrndr.extra.fx.distort + +import org.openrndr.draw.* +import org.openrndr.extra.fx.filterFragmentCode +import org.openrndr.extra.parameters.BooleanParameter +import org.openrndr.extra.parameters.Description +import org.openrndr.extra.parameters.DoubleParameter +import org.openrndr.math.Vector3 +import org.openrndr.math.transforms.transform + +@Description("Perspective plane") +class PerspectivePlane : Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("distort/perspective-plane.frag"))) { + +// @DoubleParameter("camera x", -1.0, 1.0, order = 0) + var cameraX : Double = 0.0 +// @DoubleParameter("camera y", -1.0, 1.0, order = 1) + var cameraY : Double = 0.0 +// @DoubleParameter("camera z", -1.0, 1.0, order = 2) + var cameraZ : Double = 1.0 + + + @DoubleParameter("plane x", -1.0, 1.0, order = 3) + var planeX : Double = 0.0 + @DoubleParameter("plane y", -1.0, 1.0, order = 4) + var planeY : Double = 0.0 + @DoubleParameter("plane z", -1.0, 1.0, order = 5) + var planeZ : Double = 0.5 + + @DoubleParameter("plane yaw", -180.0, 180.0, order = 6) + var planeYaw : Double = 0.0 + @DoubleParameter("plane pitch", -180.0, 180.0, order = 7) + var planePitch : Double = 0.0 + @DoubleParameter("plane roll", -180.0, 180.0, order = 8) + var planeRoll : Double = 0.0 + + + @BooleanParameter("tile input") + var tile: Boolean by parameters + + var seconds:Double by parameters + init { + seconds = 0.0 + tile = false + } + + override fun apply(source: Array, target: Array) { + source[0].generateMipmaps() + source[0].filter(MinifyingFilter.LINEAR_MIPMAP_LINEAR, MagnifyingFilter.LINEAR) + source[0].wrapU = WrapMode.REPEAT + source[0].wrapV = WrapMode.REPEAT + parameters["cameraPosition"] = Vector3(cameraX, cameraY, cameraZ) + parameters["planePosition"] = Vector3(planeX, planeY, planeZ) + parameters["planeMatrix"] = transform { + rotate(Vector3.UNIT_X, planePitch) + rotate(Vector3.UNIT_Y, planeYaw) + rotate(Vector3.UNIT_Z, planeRoll) + } + super.apply(source, target) + } +} \ No newline at end of file diff --git a/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/distort/perspective-plane.frag b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/distort/perspective-plane.frag new file mode 100644 index 00000000..9b568514 --- /dev/null +++ b/orx-fx/src/main/resources/org/openrndr/extra/fx/gl3/distort/perspective-plane.frag @@ -0,0 +1,46 @@ +#version 330 core + +// based on https://www.shadertoy.com/view/wsBSWG by bloxard + +uniform sampler2D tex0; +in vec2 v_texCoord0; +uniform vec3 cameraPosition; +uniform vec3 planePosition; +uniform float seconds; +uniform mat4 planeMatrix; +uniform bool tile; +uniform vec2 targetSize; +out vec4 o_color; + +void main() { + vec3 vCamPos = cameraPosition; + vec3 vPlanePos = planePosition; + vec3 vPlaneRight = vec3(1.0, 0.0, 0.0); + vec3 vPlaneUp = vec3(0.0, 1.0, 0.0); + + mat3 m = mat3(planeMatrix); + vPlaneUp *= m; + vPlaneRight *= m; + + vec3 vPlaneNormal = normalize(cross(vPlaneRight,vPlaneUp)); + float fPlaneDeltaNormalDistance = dot(vPlanePos,vPlaneNormal) - dot(vPlaneNormal,vCamPos); + vec4 color = vec4(0.); + for (int m = 0; m < 2; m++) { + for (int n = 0; n < 2; n++) { + vec2 s = (v_texCoord0 - vec2(0.5)) * 2.0; + s*= vec2(1.0, targetSize.y / targetSize.x); + vec3 vRayDir = normalize(vec3(s, -1.0)); + float t = fPlaneDeltaNormalDistance / dot(vPlaneNormal,vRayDir); + vec3 hitPos = vCamPos + vRayDir*t; + vec3 delta = hitPos - vPlanePos; + vec2 bary = vec2(dot(delta, vPlaneRight),dot(delta, vPlaneUp)); + + bary /= vec2(1.0, targetSize.y/targetSize.x); + bary += vec2(0.5); + if ( (tile || (bary.x >= 0.0 && bary.x <= 1.0 && bary.y >=0.0 && bary.y <= 1.0)) && t > 0.0) { + color += texture(tex0, bary); + } + } + } + o_color = color*0.25; +}