From 2425c9836b630b84e10e413c270620e9c44a6d57 Mon Sep 17 00:00:00 2001 From: Kevin Balke Date: Thu, 29 Sep 2022 21:52:05 -0700 Subject: [PATCH 1/8] Implement thin film preset --- preset/BUILD | 1 + preset/preset_list.h | 4 +-- preset/thin_film/BUILD | 37 +++++++++++++++++++++ preset/thin_film/bubble.fsh | 17 ++++++++++ preset/thin_film/composite.fsh | 31 ++++++++++++++++++ preset/thin_film/passthrough.vsh | 10 ++++++ preset/thin_film/thin_film.cc | 54 +++++++++++++++++++++++++++++++ preset/thin_film/thin_film.h | 41 ++++++++++++++++++++++++ preset/thin_film/warp.fsh | 55 ++++++++++++++++++++++++++++++++ 9 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 preset/thin_film/BUILD create mode 100644 preset/thin_film/bubble.fsh create mode 100644 preset/thin_film/composite.fsh create mode 100644 preset/thin_film/passthrough.vsh create mode 100644 preset/thin_film/thin_film.cc create mode 100644 preset/thin_film/thin_film.h create mode 100644 preset/thin_film/warp.fsh diff --git a/preset/BUILD b/preset/BUILD index 620c4d5..3ac1f01 100644 --- a/preset/BUILD +++ b/preset/BUILD @@ -15,6 +15,7 @@ PRESET_DEPS_LIST = [ "//preset/pills", "//preset/graph_preset", "//preset/space_whale_eye_warp", + "//preset/thin_film", ] cc_library( diff --git a/preset/preset_list.h b/preset/preset_list.h index 313015f..a400da7 100644 --- a/preset/preset_list.h +++ b/preset/preset_list.h @@ -24,6 +24,7 @@ #include "preset/simple_preset/simple_preset.h" #include "preset/space_whale_eye_warp/space_whale_eye_warp.h" #include "preset/template_preset/template_preset.h" +#include "preset/thin_film/thin_film.h" namespace opendrop { @@ -97,8 +98,7 @@ absl::StatusOr> GetRandomPreset( template absl::StatusOr> GetRandomPresetFromList( Args&&... args) { - return GetRandomPreset( - std::forward(args)...); + return GetRandomPreset(std::forward(args)...); } } // namespace opendrop diff --git a/preset/thin_film/BUILD b/preset/thin_film/BUILD new file mode 100644 index 0000000..420aff2 --- /dev/null +++ b/preset/thin_film/BUILD @@ -0,0 +1,37 @@ +load("//shader:shader_defs.bzl", "shader_cc_library") + +package(default_visibility = ["//:__subpackages__"]) + +cc_library( + name = "thin_film", + srcs = ["thin_film.cc"], + hdrs = ["thin_film.h"], + linkstatic = 1, + deps = [ + ":bubble", + ":passthrough", + "//preset", + "//primitive:polyline", + "//primitive:rectangle", + "//third_party:gl_helper", + "//third_party:glm_helper", + "//util/graphics:colors", + "//util/graphics:gl_interface", + "//util/graphics:gl_render_target", + "//util/graphics:gl_util", + "//util/logging", + "//util/math:vector", + "//util/status:status_macros", + ], +) + +shader_cc_library( + name = "bubble", + srcs = ["bubble.fsh"], + deps = ["//preset/common:math"], +) + +shader_cc_library( + name = "passthrough", + srcs = ["passthrough.vsh"], +) diff --git a/preset/thin_film/bubble.fsh b/preset/thin_film/bubble.fsh new file mode 100644 index 0000000..a6ae67d --- /dev/null +++ b/preset/thin_film/bubble.fsh @@ -0,0 +1,17 @@ +#version 120 + +#include "preset/common/math.shh" + +uniform vec2 pole; +varying vec2 screen_uv; + +void main() { + // float hue = 1.0 / (kEpsilon + length(screen_uv - pole)); + vec2 coord = screen_uv + pole; + vec2 coord2 = screen_uv - pole; + vec2 phase = vec2(sin_product(coord2.x, coord2.y, 12.345), + sin_product(coord2.x * 3, coord2.y * 4, 11.11)); + float hue = + 1.0 / (sin((coord.x) * 20 + phase.x) + sin((coord.y) * 20) + phase.y); + gl_FragColor = vec4(hsv_to_rgb(vec3(hue, 1.0, 1.0)), 1.0); +} diff --git a/preset/thin_film/composite.fsh b/preset/thin_film/composite.fsh new file mode 100644 index 0000000..4563031 --- /dev/null +++ b/preset/thin_film/composite.fsh @@ -0,0 +1,31 @@ +#version 120 + +uniform sampler2D render_target; +uniform ivec2 render_target_size; +uniform float power; + +varying vec2 screen_uv; + +vec2 screen_to_tex(vec2 screen_uv) { return (screen_uv + vec2(1., 1.)) * 0.5; } + +void main() { + vec2 tex_uv = screen_to_tex(screen_uv); + // Offset sampling to implement a Sobel filter kernel. The support of the + // kernel is modulated by the instantaneous power. + float offset_size_pixels = (3. + power * 10); + + // Compute the offset in normalized texture coordinates. + vec2 offset = offset_size_pixels / render_target_size; + + // Sample the texture at 3 locations: + // 1. Corresponding location for current fragment + // 2. Corresponding location for current fragment offset in X + // 3. Corresponding location for current fragment offset in Y + // + // Combine the samples with kernel [1., -0.2, -0.2] such that edges are mildly + // accentuated. + gl_FragColor = texture2D(render_target, tex_uv) * 1. + + (texture2D(render_target, tex_uv + vec2(offset.x, 0.)) + + texture2D(render_target, tex_uv + vec2(0., offset.y))) * + -0.2; +} diff --git a/preset/thin_film/passthrough.vsh b/preset/thin_film/passthrough.vsh new file mode 100644 index 0000000..704fd02 --- /dev/null +++ b/preset/thin_film/passthrough.vsh @@ -0,0 +1,10 @@ +#version 120 + +varying vec2 screen_uv; + +void main() { + screen_uv = ftransform().xy; + gl_Position = ftransform(); + gl_FrontColor = gl_Color; + gl_BackColor = gl_Color; +} diff --git a/preset/thin_film/thin_film.cc b/preset/thin_film/thin_film.cc new file mode 100644 index 0000000..76cc846 --- /dev/null +++ b/preset/thin_film/thin_film.cc @@ -0,0 +1,54 @@ +#include "preset/thin_film/thin_film.h" + +#include +#include + +#include "preset/thin_film/bubble.fsh.h" +#include "preset/thin_film/passthrough.vsh.h" +#include "third_party/gl_helper.h" +#include "third_party/glm_helper.h" +#include "util/graphics/colors.h" +#include "util/graphics/gl_util.h" +#include "util/logging/logging.h" +#include "util/status/status_macros.h" +#include "util/math/vector.h" + +namespace opendrop { + +namespace { +constexpr float kScaleFactor = 0.5f; +} + +ThinFilm::ThinFilm(std::shared_ptr texture_manager) + : Preset(texture_manager) { + thin_film_program_ = + gl::GlProgram::MakeShared(passthrough_vsh::Code(), bubble_fsh::Code()) + .value(); +} + +absl::StatusOr> ThinFilm::MakeShared( + std::shared_ptr texture_manager) { + return std::shared_ptr(new ThinFilm(texture_manager)); +} + +void ThinFilm::OnUpdateGeometry() { glViewport(0, 0, width(), height()); } + +void ThinFilm::OnDrawFrame( + absl::Span samples, std::shared_ptr state, + float alpha, std::shared_ptr output_render_target) { + float energy = state->energy(); + float power = state->power(); + + { + auto output_activation = output_render_target->Activate(); + thin_film_program_->Use(); + + gl::GlBindUniform(thin_film_program_, "pole", + UnitVectorAtAngle(energy * 2.0f) / 2.0f); + + glViewport(0, 0, width(), height()); + rectangle_.Draw(); + } +} + +} // namespace opendrop diff --git a/preset/thin_film/thin_film.h b/preset/thin_film/thin_film.h new file mode 100644 index 0000000..ce5611c --- /dev/null +++ b/preset/thin_film/thin_film.h @@ -0,0 +1,41 @@ +#ifndef PRESET_THIN_FILM_THIN_FILM_H_ +#define PRESET_THIN_FILM_THIN_FILM_H_ + +#include + +#include "absl/status/statusor.h" +#include "preset/preset.h" +#include "primitive/polyline.h" +#include "primitive/rectangle.h" +#include "third_party/glm_helper.h" +#include "util/graphics/gl_interface.h" +#include "util/graphics/gl_render_target.h" +#include "util/graphics/gl_texture_manager.h" + +namespace opendrop { + +class ThinFilm : public Preset { + public: + static absl::StatusOr> MakeShared( + std::shared_ptr texture_manager); + + std::string name() const override { return "ThinFilm"; } + + protected: + ThinFilm(std::shared_ptr texture_manager); + + void OnDrawFrame( + absl::Span samples, std::shared_ptr state, + float alpha, + std::shared_ptr output_render_target) override; + void OnUpdateGeometry() override; + + private: + std::shared_ptr thin_film_program_; + + Rectangle rectangle_; +}; + +} // namespace opendrop + +#endif // PRESET_THIN_FILM_THIN_FILM_H_ diff --git a/preset/thin_film/warp.fsh b/preset/thin_film/warp.fsh new file mode 100644 index 0000000..1876f00 --- /dev/null +++ b/preset/thin_film/warp.fsh @@ -0,0 +1,55 @@ +#version 120 + +varying vec2 screen_uv; + +uniform sampler2D last_frame; +uniform ivec2 last_frame_size; +uniform float energy; +uniform float power; + +// Rotates a screen UV coordinate around the origin by `angle`. +vec2 rotate(vec2 screen_uv, float angle) { + float c = cos(angle); + float s = sin(angle); + + return vec2(c * screen_uv.x - s * screen_uv.y, + s * screen_uv.x + c * screen_uv.y); +} + +// Converts a normalized screen coordinate to a normalized texture coordinate. +vec2 screen_to_tex(vec2 screen_uv) { return (screen_uv + vec2(1., 1.)) * 0.5; } + +// Zooms a screen UV coordinate by displacing it along its axis. +vec2 zoom(vec2 screen_uv, float zoom) { return screen_uv * zoom; } + +// Returns the product of two sinusoids with the given coefficients of `arg`. +// Choosing the coefficients such that the number of decimal places required to +// represent their ratio is maximized will give a greater appearance of +// "randomness". +float sin_product(float coeff_a, float coeff_b, float arg) { + return sin(coeff_a * arg) * sin(coeff_b * arg); +} + +void main() { + vec2 texture_uv = vec2(0.0, 0.0); + + // Zoom the texture by an amount equal to a scaled sinusoid of the energy + // times the power. This has the effect of the accumulated image zooming + // inwards and then outwards in a periodic fashion, with the period of the + // alternation being inversely proportional to the current intensity of the + // audio. We multiply in the power such that instantaneous changes in the + // audio cause more immediately perceptible "jumps" in the zoom effect. + texture_uv = zoom(screen_uv, sin(energy * 20) * 0.3 * power + 1.); + + // Rotate the texture by a pseudo-random amount that varies by `energy`. + // Additionally multiply in `power` for the same reason as above. + texture_uv = + rotate(texture_uv, sin_product(100 / 7.334, 10 / 9.225, energy) * power); + + texture_uv = screen_to_tex(texture_uv); + + // Mix the fragment color with the previously sampled color. Multiply the + // sampled result by a value less than unity such that the energy input by the + // drawn GL primitives dissipates over time. + gl_FragColor = gl_Color * 0.5 + texture2D(last_frame, texture_uv) * 0.95; +} From 9783e91bbd8ab9664ec3aa943f299475a0446a30 Mon Sep 17 00:00:00 2001 From: Kevin Balke Date: Thu, 29 Sep 2022 23:02:19 -0700 Subject: [PATCH 2/8] Implemented some additional controls --- preset/common/math.shh | 46 +++++++++++++++++++++++++++++++++++ preset/thin_film/BUILD | 2 ++ preset/thin_film/bubble.fsh | 29 ++++++++++++++++------ preset/thin_film/thin_film.cc | 22 ++++++++++++++++- preset/thin_film/thin_film.h | 4 +++ 5 files changed, 95 insertions(+), 8 deletions(-) diff --git a/preset/common/math.shh b/preset/common/math.shh index 31e14e7..ef0d06a 100644 --- a/preset/common/math.shh +++ b/preset/common/math.shh @@ -4,6 +4,13 @@ const float kPi = 3.141592653589793; const float kEpsilon = 1e-6; +float safe_sqrt(float value) { + if (value < 1) { + return 1; + } + return sqrt(value); +} + vec2 unit_at_angle(float angle) { return vec2(cos(angle), sin(angle)); } // Rotates a screen UV coordinate around the origin by `angle`. @@ -49,6 +56,12 @@ vec4 shift_hue(vec4 color, float hue) { color.w); } +vec3 hsv_to_rgb(vec3 c) { + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + float sin_product_range(float coeff_a, float coeff_b, float min, float max, float arg) { return sin_product(coeff_a, coeff_b, arg) * (max - min) + min; @@ -104,4 +117,37 @@ vec2 uv_warp_spiral(vec2 uv, float aspect_ratio) { return rotate(uv, length(uv) * aspect_ratio); } +// Warps a UV coordinate by a fisheye effect. +vec2 uv_warp_fisheye(vec2 uv, float fisheye_coeff) { + return uv * mix(1, length(uv), fisheye_coeff); +} + +// Limits the minimum magnitude of a value. Limit policy is selectable with the +// `policy` argument. The sign of the return value is the same as `value`. +const int kLimitMinMagnitudePolicy_Absolute = 0; +const int kLimitMinMagnitudePolicy_Rolloff = 1; +float limit_min_magnitude(float value, float minimum_magnitude, int policy) { + float scale = abs(value / minimum_magnitude); + + if (policy == kLimitMinMagnitudePolicy_Absolute) { + if (scale > 1) { + return value; + } else { + return value / scale; + } + } else if (policy == kLimitMinMagnitudePolicy_Rolloff) { + const float kRolloffStartScale = 2; + if (scale > kRolloffStartScale) { + return value; + } else if (scale > 1) { + return value / mix(1, scale, kRolloffStartScale - scale); + } else { + return value / scale; + } + } else { + // Unknown policy. Return the minimum magnitude. + return minimum_magnitude; + } +} + #endif // PRESET_COMMON_MATH_SHH_ diff --git a/preset/thin_film/BUILD b/preset/thin_film/BUILD index 420aff2..412172c 100644 --- a/preset/thin_film/BUILD +++ b/preset/thin_film/BUILD @@ -10,6 +10,7 @@ cc_library( deps = [ ":bubble", ":passthrough", + "//debug:control_injector", "//preset", "//primitive:polyline", "//primitive:rectangle", @@ -21,6 +22,7 @@ cc_library( "//util/graphics:gl_util", "//util/logging", "//util/math:vector", + "//util/signal:filter", "//util/status:status_macros", ], ) diff --git a/preset/thin_film/bubble.fsh b/preset/thin_film/bubble.fsh index a6ae67d..e094701 100644 --- a/preset/thin_film/bubble.fsh +++ b/preset/thin_film/bubble.fsh @@ -5,13 +5,28 @@ uniform vec2 pole; varying vec2 screen_uv; +uniform sampler2D last_frame; + +uniform float rotate_coeff; +uniform float phase_x_coeff; +uniform float phase_y_coeff; +uniform float ripple_hue; +uniform float min_value_coeff; +uniform float fisheye_coeff; + void main() { // float hue = 1.0 / (kEpsilon + length(screen_uv - pole)); - vec2 coord = screen_uv + pole; - vec2 coord2 = screen_uv - pole; - vec2 phase = vec2(sin_product(coord2.x, coord2.y, 12.345), - sin_product(coord2.x * 3, coord2.y * 4, 11.11)); - float hue = - 1.0 / (sin((coord.x) * 20 + phase.x) + sin((coord.y) * 20) + phase.y); - gl_FragColor = vec4(hsv_to_rgb(vec3(hue, 1.0, 1.0)), 1.0); + vec2 effect_uv = uv_warp_fisheye(screen_uv, fisheye_coeff); + vec2 coord = effect_uv + pole; + vec2 coord2 = effect_uv - pole; + vec2 phase = vec2( + sin_product(coord2.x, coord2.y, 12.345 * (1 + phase_x_coeff)), + sin_product(coord2.x * 3, coord2.y * 4, 11.11 * (1 + phase_y_coeff))); + coord = rotate(coord, 4 * kPi * rotate_coeff); + float color_value = + 1.0 / limit_min_magnitude( + sin((coord.x) * 20 + phase.x) + sin((coord.y) * 20 + phase.y), + min_value_coeff, kLimitMinMagnitudePolicy_Rolloff); + gl_FragColor = + vec4(hsv_to_rgb(vec3(ripple_hue, 1.0, mod(color_value, 1))), 1.0); } diff --git a/preset/thin_film/thin_film.cc b/preset/thin_film/thin_film.cc index 76cc846..da48360 100644 --- a/preset/thin_film/thin_film.cc +++ b/preset/thin_film/thin_film.cc @@ -3,6 +3,7 @@ #include #include +#include "debug/control_injector.h" #include "preset/thin_film/bubble.fsh.h" #include "preset/thin_film/passthrough.vsh.h" #include "third_party/gl_helper.h" @@ -10,8 +11,8 @@ #include "util/graphics/colors.h" #include "util/graphics/gl_util.h" #include "util/logging/logging.h" -#include "util/status/status_macros.h" #include "util/math/vector.h" +#include "util/status/status_macros.h" namespace opendrop { @@ -46,6 +47,25 @@ void ThinFilm::OnDrawFrame( gl::GlBindUniform(thin_film_program_, "pole", UnitVectorAtAngle(energy * 2.0f) / 2.0f); + gl::GlBindUniform(thin_film_program_, "rotate_coeff", + rot_filter_->ProcessSample(SIGINJECT_OVERRIDE( + "thin_film_rotate_coeff", 0.0f, 0.0f, 1.0f))); + gl::GlBindUniform( + thin_film_program_, "phase_x_coeff", + SIGINJECT_OVERRIDE("thin_film_phase_x_coeff", 0.0f, 0.0f, 1.0f)); + gl::GlBindUniform( + thin_film_program_, "phase_y_coeff", + SIGINJECT_OVERRIDE("thin_film_phase_y_coeff", 0.0f, 0.0f, 1.0f)); + gl::GlBindUniform( + thin_film_program_, "ripple_hue", + SIGINJECT_OVERRIDE("thin_film_ripple_hue", 0.0f, 0.0f, 1.0f)); + gl::GlBindUniform( + thin_film_program_, "min_value_coeff", + SIGINJECT_OVERRIDE("thin_film_min_value_coeff", 0.0f, 0.0f, 1.0f)); + gl::GlBindUniform( + thin_film_program_, "fisheye_coeff", + SIGINJECT_OVERRIDE("thin_film_fisheye_coeff", 0.0f, 0.0f, 1.0f)); + glViewport(0, 0, width(), height()); rectangle_.Draw(); } diff --git a/preset/thin_film/thin_film.h b/preset/thin_film/thin_film.h index ce5611c..c66c2b7 100644 --- a/preset/thin_film/thin_film.h +++ b/preset/thin_film/thin_film.h @@ -11,6 +11,7 @@ #include "util/graphics/gl_interface.h" #include "util/graphics/gl_render_target.h" #include "util/graphics/gl_texture_manager.h" +#include "util/signal/filter.h" namespace opendrop { @@ -34,6 +35,9 @@ class ThinFilm : public Preset { std::shared_ptr thin_film_program_; Rectangle rectangle_; + + std::shared_ptr rot_filter_ = + IirSinglePoleFilter(0.01, IirSinglePoleFilterType::kLowpass); }; } // namespace opendrop From 807978ed52bfbc19f7093fcef25f3eec82d4903a Mon Sep 17 00:00:00 2001 From: Kevin Balke Date: Thu, 29 Sep 2022 23:02:27 -0700 Subject: [PATCH 3/8] Added midimix config --- configs/midimix.textproto | 102 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 configs/midimix.textproto diff --git a/configs/midimix.textproto b/configs/midimix.textproto new file mode 100644 index 0000000..9f7b7a4 --- /dev/null +++ b/configs/midimix.textproto @@ -0,0 +1,102 @@ +control_mappings { + key: "thin_film_fisheye_coeff" + value: "control_change:0:50:0" +} +control_mappings { + key: "thin_film_min_value_coeff" + value: "control_change:0:46:0" +} +control_mappings { + key: "thin_film_phase_x_coeff" + value: "control_change:0:20:0" +} +control_mappings { + key: "thin_film_phase_y_coeff" + value: "control_change:0:24:0" +} +control_mappings { + key: "thin_film_ripple_hue" + value: "control_change:0:28:0" +} +control_mappings { + key: "thin_film_rotate_coeff" + value: "control_change:0:16:0" +} +signals_by_name { + key: "thin_film_fisheye_coeff" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_min_value_coeff" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_phase_x_coeff" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_phase_y_coeff" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_ripple_hue" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_rotate_coeff" + value { + low: 0 + high: 1 + } +} +counters_by_name { + key: "next_preset" + value { + low: 0 + high: 0 + value: 0 + } +} +controls_by_name { + key: "control_change:0:16:0" + value: 0.527559042 +} +controls_by_name { + key: "control_change:0:20:0" + value: 0.527559042 +} +controls_by_name { + key: "control_change:0:24:0" + value: 1 +} +controls_by_name { + key: "control_change:0:28:0" + value: 0.228346452 +} +controls_by_name { + key: "control_change:0:46:0" + value: 1 +} +controls_by_name { + key: "control_change:0:47:0" + value: 0 +} +controls_by_name { + key: "control_change:0:50:0" + value: 0.937007844 +} From d0a8a9c919cb889a510aa560e025d594d7e3bc4f Mon Sep 17 00:00:00 2001 From: Kevin Balke Date: Fri, 30 Sep 2022 00:03:52 -0700 Subject: [PATCH 4/8] Brought over double-buffer changes from liquid-slash --- util/graphics/gl_render_target.cc | 44 ++++++++++++++++++------------- util/graphics/gl_render_target.h | 35 ++++++++++++++++++++++-- util/graphics/gl_util.cc | 6 ++++- util/graphics/gl_util.h | 1 + 4 files changed, 65 insertions(+), 21 deletions(-) diff --git a/util/graphics/gl_render_target.cc b/util/graphics/gl_render_target.cc index 7418a4c..be294ba 100644 --- a/util/graphics/gl_render_target.cc +++ b/util/graphics/gl_render_target.cc @@ -14,8 +14,6 @@ GlRenderTargetActivation::GlRenderTargetActivation( // Configure the backing texture. glBindFramebuffer(GL_FRAMEBUFFER, render_target_->framebuffer_handle()); glBindRenderbuffer(GL_RENDERBUFFER, render_target_->renderbuffer_handle()); - LOG(INFO) << "Bound framebuffer " << render_target_->framebuffer_handle() - << " and renderbuffer " << render_target_->renderbuffer_handle(); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_target_->texture_handle(), 0); @@ -86,9 +84,11 @@ GlRenderTarget::GlRenderTarget( // Create a new framebuffer. glGenFramebuffers(1, &framebuffer_handle_); LOG(DEBUG) << "Generated framebuffer: " << framebuffer_handle_; - // Generate a backing texture. - glGenTextures(1, &texture_handle_); - LOG(DEBUG) << "Generated texture: " << texture_handle_; + // Generate backing textures. + glGenTextures(1, &front_texture_handle_); + LOG(DEBUG) << "Generated front texture: " << front_texture_handle_; + glGenTextures(1, &back_texture_handle_); + LOG(DEBUG) << "Generated back texture: " << back_texture_handle_; if (options_.enable_depth) { glGenTextures(1, &depth_buffer_handle_); @@ -109,13 +109,15 @@ absl::StatusOr> GlRenderTarget::MakeShared( } GlRenderTarget::~GlRenderTarget() { - LOG(INFO) << "Disposing render target with texture handle: " << texture_handle_; + LOG(INFO) << "Disposing render target with texture handle: " + << front_texture_handle_; if (options_.enable_depth) { glDeleteTextures(1, &depth_buffer_handle_); } texture_manager_->Deallocate(texture_unit_); - glDeleteTextures(1, &texture_handle_); + glDeleteTextures(1, &front_texture_handle_); + glDeleteTextures(1, &back_texture_handle_); glDeleteFramebuffers(1, &framebuffer_handle_); glDeleteFramebuffers(1, &renderbuffer_handle_); } @@ -130,19 +132,21 @@ void GlRenderTarget::UpdateGeometry(int width, int height) { return; } - glBindTexture(GL_TEXTURE_2D, texture_handle_); - LOG(DEBUG) << "Bound RGBA texture: " << texture_handle_; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, - GL_UNSIGNED_BYTE, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + for (auto handle : {front_texture_handle_, back_texture_handle_}) { + glBindTexture(GL_TEXTURE_2D, handle); + LOG(DEBUG) << "Bound RGBA texture: " << handle; + glTexImage2D(GL_TEXTURE_2D, 0, GlTextureInternalFormat(), width_, height_, + 0, GL_RGBA, GlTextureType(), 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } if (options_.enable_depth) { glBindTexture(GL_TEXTURE_2D, depth_buffer_handle_); LOG(DEBUG) << "Bound depth texture: " << depth_buffer_handle_; glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width_, height_, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } glBindTexture(GL_TEXTURE_2D, 0); LOG(DEBUG) << "Unbound texture"; @@ -162,9 +166,13 @@ bool GlRenderTarget::swap_texture_unit(GlRenderTarget* other) { return false; } - int intermediate_texture_handle = other->texture_handle_; - other->texture_handle_ = texture_handle_; - texture_handle_ = intermediate_texture_handle; + std::swap(front_texture_handle_, other->front_texture_handle_); + return true; +} + +bool GlRenderTarget::swap() { + std::unique_lock lock(render_target_mu_); + std::swap(front_texture_handle_, back_texture_handle_); return true; } diff --git a/util/graphics/gl_render_target.h b/util/graphics/gl_render_target.h index 28ad625..be29d80 100644 --- a/util/graphics/gl_render_target.h +++ b/util/graphics/gl_render_target.h @@ -5,6 +5,7 @@ #include #include "absl/status/statusor.h" +#include "third_party/gl_helper.h" #include "third_party/glm_helper.h" #include "util/graphics/gl_interface.h" #include "util/graphics/gl_texture_manager.h" @@ -24,12 +25,18 @@ class GlRenderTargetActivation { class GlRenderTarget : public std::enable_shared_from_this { public: + enum class TextureType { + kUnsignedByte, + kHalfFloat, + }; // Construction options for GlRenderTarget. struct Options { // Whether or not to support a depth buffer for the render target. When // `true`, there will be a depth buffer attachment and associated texture // allocated for the render target. bool enable_depth = false; + + TextureType type = TextureType::kUnsignedByte; }; static absl::StatusOr> MakeShared( @@ -49,7 +56,8 @@ class GlRenderTarget : public std::enable_shared_from_this { int texture_unit() const { return texture_unit_; } unsigned int renderbuffer_handle() const { return renderbuffer_handle_; } unsigned int framebuffer_handle() const { return framebuffer_handle_; } - unsigned int texture_handle() const { return texture_handle_; } + unsigned int texture_handle() const { return front_texture_handle_; } + unsigned int back_texture_handle() const { return back_texture_handle_; } unsigned int depth_buffer_handle() const { return depth_buffer_handle_; } const Options& options() const { return options_; } int width() { @@ -66,18 +74,41 @@ class GlRenderTarget : public std::enable_shared_from_this { } bool swap_texture_unit(GlRenderTarget* other); + // Swap front/back textures. + bool swap(); private: GlRenderTarget(int width, int height, int texture_unit, std::shared_ptr texture_manager, Options options); + GLuint GlTextureType() { + switch (options_.type) { + case TextureType::kHalfFloat: + return GL_HALF_FLOAT; + case TextureType::kUnsignedByte: + return GL_UNSIGNED_BYTE; + } + return {}; + } + + GLuint GlTextureInternalFormat() { + switch (options_.type) { + case TextureType::kHalfFloat: + return GL_RGBA16F; + case TextureType::kUnsignedByte: + return GL_RGBA; + } + return {}; + } + std::mutex render_target_mu_; int width_, height_; int texture_unit_; unsigned int framebuffer_handle_; unsigned int renderbuffer_handle_; - unsigned int texture_handle_; + unsigned int front_texture_handle_; + unsigned int back_texture_handle_; unsigned int depth_buffer_handle_; std::shared_ptr texture_manager_; diff --git a/util/graphics/gl_util.cc b/util/graphics/gl_util.cc index 70d632c..1809d17 100644 --- a/util/graphics/gl_util.cc +++ b/util/graphics/gl_util.cc @@ -63,7 +63,11 @@ void GlBindRenderTargetTextureToUniform( return; } glActiveTexture(GL_TEXTURE0 + render_target->texture_unit()); - glBindTexture(GL_TEXTURE_2D, render_target->texture_handle()); + if (binding_options.back) { + glBindTexture(GL_TEXTURE_2D, render_target->back_texture_handle()); + } else { + glBindTexture(GL_TEXTURE_2D, render_target->texture_handle()); + } ConfigureBindingOptions(binding_options); diff --git a/util/graphics/gl_util.h b/util/graphics/gl_util.h index 1bbc1de..493c06f 100644 --- a/util/graphics/gl_util.h +++ b/util/graphics/gl_util.h @@ -37,6 +37,7 @@ struct GlTextureBindingOptions { GlTextureSamplingMode sampling_mode = GlTextureSamplingMode::kClamp; GlTextureFilteringMode filtering_mode = GlTextureFilteringMode::kLinear; glm::vec4 border_color = glm::vec4(0, 0, 0, 0); + bool back = false; }; void GlClear(glm::vec4 color); From cad079bad09b2a73d5c124e8c0ec740095003031 Mon Sep 17 00:00:00 2001 From: Kevin Balke Date: Fri, 30 Sep 2022 00:04:01 -0700 Subject: [PATCH 5/8] This is pretty sick --- configs/midimix.textproto | 42 ++++++++++++++++++++++++++++++----- preset/common/math.shh | 28 +++++++++++++++++++++++ preset/thin_film/bubble.fsh | 16 +++++++++---- preset/thin_film/thin_film.cc | 12 ++++++++++ preset/thin_film/thin_film.h | 2 ++ 5 files changed, 90 insertions(+), 10 deletions(-) diff --git a/configs/midimix.textproto b/configs/midimix.textproto index 9f7b7a4..87ad701 100644 --- a/configs/midimix.textproto +++ b/configs/midimix.textproto @@ -2,6 +2,10 @@ control_mappings { key: "thin_film_fisheye_coeff" value: "control_change:0:50:0" } +control_mappings { + key: "thin_film_folds_coeff" + value: "control_change:0:58:0" +} control_mappings { key: "thin_film_min_value_coeff" value: "control_change:0:46:0" @@ -22,6 +26,10 @@ control_mappings { key: "thin_film_rotate_coeff" value: "control_change:0:16:0" } +control_mappings { + key: "thin_film_shift_hue_coeff" + value: "control_change:0:54:0" +} signals_by_name { key: "thin_film_fisheye_coeff" value { @@ -29,6 +37,13 @@ signals_by_name { high: 1 } } +signals_by_name { + key: "thin_film_folds_coeff" + value { + low: 0.02 + high: 3 + } +} signals_by_name { key: "thin_film_min_value_coeff" value { @@ -64,6 +79,13 @@ signals_by_name { high: 1 } } +signals_by_name { + key: "thin_film_shift_hue_coeff" + value { + low: 0 + high: 1 + } +} counters_by_name { key: "next_preset" value { @@ -74,23 +96,23 @@ counters_by_name { } controls_by_name { key: "control_change:0:16:0" - value: 0.527559042 + value: 0.645669281 } controls_by_name { key: "control_change:0:20:0" - value: 0.527559042 + value: 0.0708661452 } controls_by_name { key: "control_change:0:24:0" - value: 1 + value: 0.275590539 } controls_by_name { key: "control_change:0:28:0" - value: 0.228346452 + value: 0 } controls_by_name { key: "control_change:0:46:0" - value: 1 + value: 0.858267725 } controls_by_name { key: "control_change:0:47:0" @@ -98,5 +120,13 @@ controls_by_name { } controls_by_name { key: "control_change:0:50:0" - value: 0.937007844 + value: 0.866141737 +} +controls_by_name { + key: "control_change:0:54:0" + value: 0.267716527 +} +controls_by_name { + key: "control_change:0:58:0" + value: 0.251968503 } diff --git a/preset/common/math.shh b/preset/common/math.shh index ef0d06a..530e31b 100644 --- a/preset/common/math.shh +++ b/preset/common/math.shh @@ -4,6 +4,28 @@ const float kPi = 3.141592653589793; const float kEpsilon = 1e-6; +// Folds a value in the range [0, 1] a number of times over on the number line. +// E.g., for 2 `folds`: +// +// 1| +// | ^ +// O | / \ +// U | / \ +// T | / \ +// |/ \ +// 0+----------- +// 0 1 +// IN +// +// `folds` can be any positive real value ([0, +inf]). +float fold(float value, float folds) { + float triangle_value = mod(value * folds, 2); + if (triangle_value < 1) { + return triangle_value; + } + return 2 - triangle_value; +} + float safe_sqrt(float value) { if (value < 1) { return 1; @@ -122,6 +144,12 @@ vec2 uv_warp_fisheye(vec2 uv, float fisheye_coeff) { return uv * mix(1, length(uv), fisheye_coeff); } +// Warps a UV coordinate by folding it over itself a number of times. +vec2 uv_warp_fold(vec2 uv, vec2 center, vec2 folds) { + return vec2(fold(abs(uv.x - center.x), folds.x), + fold(abs(uv.y - center.y), folds.y)); +} + // Limits the minimum magnitude of a value. Limit policy is selectable with the // `policy` argument. The sign of the return value is the same as `value`. const int kLimitMinMagnitudePolicy_Absolute = 0; diff --git a/preset/thin_film/bubble.fsh b/preset/thin_film/bubble.fsh index e094701..e22c1f9 100644 --- a/preset/thin_film/bubble.fsh +++ b/preset/thin_film/bubble.fsh @@ -11,22 +11,30 @@ uniform float rotate_coeff; uniform float phase_x_coeff; uniform float phase_y_coeff; uniform float ripple_hue; +uniform float shift_hue_coeff; uniform float min_value_coeff; uniform float fisheye_coeff; +uniform float folds_coeff; void main() { // float hue = 1.0 / (kEpsilon + length(screen_uv - pole)); vec2 effect_uv = uv_warp_fisheye(screen_uv, fisheye_coeff); - vec2 coord = effect_uv + pole; - vec2 coord2 = effect_uv - pole; + vec2 coord = rotate(effect_uv, 4 * kPi * rotate_coeff) + pole; + vec2 coord2 = rotate(effect_uv, 4 * kPi * rotate_coeff) - pole; vec2 phase = vec2( sin_product(coord2.x, coord2.y, 12.345 * (1 + phase_x_coeff)), sin_product(coord2.x * 3, coord2.y * 4, 11.11 * (1 + phase_y_coeff))); - coord = rotate(coord, 4 * kPi * rotate_coeff); float color_value = 1.0 / limit_min_magnitude( sin((coord.x) * 20 + phase.x) + sin((coord.y) * 20 + phase.y), min_value_coeff, kLimitMinMagnitudePolicy_Rolloff); - gl_FragColor = + vec4 color = vec4(hsv_to_rgb(vec3(ripple_hue, 1.0, mod(color_value, 1))), 1.0); + gl_FragColor = + mix(color, + shift_hue(texture2D(last_frame, screen_to_tex(uv_warp_fold( + screen_uv * 2, vec2(0, 0), + vec2(1, 1) * folds_coeff))), + shift_hue_coeff), + length(color.rgb)); } diff --git a/preset/thin_film/thin_film.cc b/preset/thin_film/thin_film.cc index da48360..6b3216e 100644 --- a/preset/thin_film/thin_film.cc +++ b/preset/thin_film/thin_film.cc @@ -40,6 +40,9 @@ void ThinFilm::OnDrawFrame( float energy = state->energy(); float power = state->power(); + // Write a test to assert that rendering is done into the back buffer (zero + // frame delay to presentation). + // output_render_target->swap(); { auto output_activation = output_render_target->Activate(); thin_film_program_->Use(); @@ -47,6 +50,8 @@ void ThinFilm::OnDrawFrame( gl::GlBindUniform(thin_film_program_, "pole", UnitVectorAtAngle(energy * 2.0f) / 2.0f); + gl::GlBindRenderTargetTextureToUniform( + thin_film_program_, "last_frame", output_render_target, {.back = true}); gl::GlBindUniform(thin_film_program_, "rotate_coeff", rot_filter_->ProcessSample(SIGINJECT_OVERRIDE( "thin_film_rotate_coeff", 0.0f, 0.0f, 1.0f))); @@ -59,15 +64,22 @@ void ThinFilm::OnDrawFrame( gl::GlBindUniform( thin_film_program_, "ripple_hue", SIGINJECT_OVERRIDE("thin_film_ripple_hue", 0.0f, 0.0f, 1.0f)); + gl::GlBindUniform( + thin_film_program_, "shift_hue_coeff", + SIGINJECT_OVERRIDE("thin_film_shift_hue_coeff", 0.0f, 0.0f, 1.0f)); gl::GlBindUniform( thin_film_program_, "min_value_coeff", SIGINJECT_OVERRIDE("thin_film_min_value_coeff", 0.0f, 0.0f, 1.0f)); gl::GlBindUniform( thin_film_program_, "fisheye_coeff", SIGINJECT_OVERRIDE("thin_film_fisheye_coeff", 0.0f, 0.0f, 1.0f)); + gl::GlBindUniform(thin_film_program_, "folds_coeff", + folds_filter_->ProcessSample(SIGINJECT_OVERRIDE( + "thin_film_folds_coeff", 0.0f, 0.02f, 1.5f))); glViewport(0, 0, width(), height()); rectangle_.Draw(); + output_render_target->swap(); } } diff --git a/preset/thin_film/thin_film.h b/preset/thin_film/thin_film.h index c66c2b7..22189cd 100644 --- a/preset/thin_film/thin_film.h +++ b/preset/thin_film/thin_film.h @@ -38,6 +38,8 @@ class ThinFilm : public Preset { std::shared_ptr rot_filter_ = IirSinglePoleFilter(0.01, IirSinglePoleFilterType::kLowpass); + std::shared_ptr folds_filter_ = + IirSinglePoleFilter(0.05, IirSinglePoleFilterType::kLowpass); }; } // namespace opendrop From c8acdb787351decc2065aefc7b68030cd92b819d Mon Sep 17 00:00:00 2001 From: Kevin Balke Date: Fri, 30 Sep 2022 01:50:36 -0700 Subject: [PATCH 6/8] Extra dope --- configs/midimix.textproto | 150 +++++++++++++++++++++++++++++++--- preset/common/math.shh | 16 ++++ preset/thin_film/bubble.fsh | 45 +++++++--- preset/thin_film/thin_film.cc | 33 ++++++++ preset/thin_film/thin_film.h | 7 ++ 5 files changed, 229 insertions(+), 22 deletions(-) diff --git a/configs/midimix.textproto b/configs/midimix.textproto index 87ad701..ada2e30 100644 --- a/configs/midimix.textproto +++ b/configs/midimix.textproto @@ -1,3 +1,11 @@ +buttons: 1 +buttons: 4 +buttons: 7 +buttons: 9 +buttons: 10 +buttons: 13 +buttons: 16 +buttons: 19 control_mappings { key: "thin_film_fisheye_coeff" value: "control_change:0:50:0" @@ -6,10 +14,18 @@ control_mappings { key: "thin_film_folds_coeff" value: "control_change:0:58:0" } +control_mappings { + key: "thin_film_force_mix_coeff" + value: "control_change:0:17:0" +} control_mappings { key: "thin_film_min_value_coeff" value: "control_change:0:46:0" } +control_mappings { + key: "thin_film_mix_prescale_coeff" + value: "control_change:0:21:0" +} control_mappings { key: "thin_film_phase_x_coeff" value: "control_change:0:20:0" @@ -41,7 +57,14 @@ signals_by_name { key: "thin_film_folds_coeff" value { low: 0.02 - high: 3 + high: 1.5 + } +} +signals_by_name { + key: "thin_film_force_mix_coeff" + value { + low: 0.02 + high: 1.5 } } signals_by_name { @@ -51,6 +74,13 @@ signals_by_name { high: 1 } } +signals_by_name { + key: "thin_film_mix_prescale_coeff" + value { + low: 0 + high: 1.5 + } +} signals_by_name { key: "thin_film_phase_x_coeff" value { @@ -86,6 +116,62 @@ signals_by_name { high: 1 } } +button_mappings { + key: "invert_coords" + value: 7 +} +button_mappings { + key: "invert_hue" + value: 4 +} +button_mappings { + key: "invert_recursive_coords" + value: 10 +} +button_mappings { + key: "invert_screen" + value: 1 +} +button_mappings { + key: "swap_coords" + value: 13 +} +button_mappings { + key: "swap_recursive_coords" + value: 16 +} +counters_by_name { + key: "invert_coords" + value { + low: 0 + high: 0 + value: 0 + } +} +counters_by_name { + key: "invert_hue" + value { + low: 0 + high: 0 + value: 0 + } +} +counters_by_name { + key: "invert_recursive_coords" + value { + low: 0 + high: 0 + value: 0 + } +} +counters_by_name { + key: "invert_screen" + value { + low: 0 + high: 0 + value: 0 + } +} counters_by_name { key: "next_preset" value { @@ -94,39 +180,83 @@ counters_by_name { value: 0 } } +counters_by_name { + key: "swap_coords" + value { + low: 0 + high: 0 + value: 0 + } +} +counters_by_name { + key: "swap_recursive_coords" + value { + low: 0 + high: 0 + value: 0 + } +} controls_by_name { key: "control_change:0:16:0" - value: 0.645669281 + value: 0.606299222 +} +controls_by_name { + key: "control_change:0:17:0" + value: 0.314960629 } controls_by_name { key: "control_change:0:20:0" - value: 0.0708661452 + value: 1 +} +controls_by_name { + key: "control_change:0:21:0" + value: 0.858267725 } controls_by_name { key: "control_change:0:24:0" - value: 0.275590539 + value: 0.299212605 +} +controls_by_name { + key: "control_change:0:25:0" + value: 0.40157479 } controls_by_name { key: "control_change:0:28:0" - value: 0 + value: 0.937007844 +} +controls_by_name { + key: "control_change:0:29:0" + value: 0.228346452 } controls_by_name { key: "control_change:0:46:0" - value: 0.858267725 + value: 0.338582665 } controls_by_name { key: "control_change:0:47:0" - value: 0 + value: 0.425196856 } controls_by_name { key: "control_change:0:50:0" - value: 0.866141737 + value: 0.897637784 } controls_by_name { - key: "control_change:0:54:0" + key: "control_change:0:51:0" value: 0.267716527 } +controls_by_name { + key: "control_change:0:54:0" + value: 0.51968503 +} +controls_by_name { + key: "control_change:0:55:0" + value: 0.716535449 +} controls_by_name { key: "control_change:0:58:0" - value: 0.251968503 + value: 0.40157479 +} +controls_by_name { + key: "control_change:0:59:0" + value: 0.11811024 } diff --git a/preset/common/math.shh b/preset/common/math.shh index 530e31b..8579e09 100644 --- a/preset/common/math.shh +++ b/preset/common/math.shh @@ -150,6 +150,22 @@ vec2 uv_warp_fold(vec2 uv, vec2 center, vec2 folds) { fold(abs(uv.y - center.y), folds.y)); } +vec2 uv_warp_invert(vec2 uv, bool invert) { + if (invert) { + return -uv; + } else { + return uv; + } +} + +vec2 uv_warp_swap(vec2 uv, bool swap) { + if (swap) { + return uv.yx; + } else { + return uv; + } +} + // Limits the minimum magnitude of a value. Limit policy is selectable with the // `policy` argument. The sign of the return value is the same as `value`. const int kLimitMinMagnitudePolicy_Absolute = 0; diff --git a/preset/thin_film/bubble.fsh b/preset/thin_film/bubble.fsh index e22c1f9..e916a01 100644 --- a/preset/thin_film/bubble.fsh +++ b/preset/thin_film/bubble.fsh @@ -15,26 +15,47 @@ uniform float shift_hue_coeff; uniform float min_value_coeff; uniform float fisheye_coeff; uniform float folds_coeff; +uniform float force_mix_coeff; +uniform float mix_prescale_coeff; +uniform bool invert_screen; +uniform bool invert_hue; +uniform bool invert_coords; +uniform bool swap_coords; +uniform bool swap_recursive_coords; +uniform bool invert_recursive_coords; void main() { - // float hue = 1.0 / (kEpsilon + length(screen_uv - pole)); - vec2 effect_uv = uv_warp_fisheye(screen_uv, fisheye_coeff); + vec2 in_screen_uv = + uv_warp_swap(uv_warp_invert(screen_uv, invert_coords), swap_coords); + vec2 effect_uv = uv_warp_fisheye(in_screen_uv, fisheye_coeff); vec2 coord = rotate(effect_uv, 4 * kPi * rotate_coeff) + pole; vec2 coord2 = rotate(effect_uv, 4 * kPi * rotate_coeff) - pole; vec2 phase = vec2( sin_product(coord2.x, coord2.y, 12.345 * (1 + phase_x_coeff)), - sin_product(coord2.x * 3, coord2.y * 4, 11.11 * (1 + phase_y_coeff))); + sin_product(coord2.x * 3, coord2.y * 4, 1.11 * (1 + 10 * phase_y_coeff))); float color_value = 1.0 / limit_min_magnitude( sin((coord.x) * 20 + phase.x) + sin((coord.y) * 20 + phase.y), min_value_coeff, kLimitMinMagnitudePolicy_Rolloff); - vec4 color = - vec4(hsv_to_rgb(vec3(ripple_hue, 1.0, mod(color_value, 1))), 1.0); - gl_FragColor = - mix(color, - shift_hue(texture2D(last_frame, screen_to_tex(uv_warp_fold( - screen_uv * 2, vec2(0, 0), - vec2(1, 1) * folds_coeff))), - shift_hue_coeff), - length(color.rgb)); + + float input_hue = ripple_hue; + if (invert_hue) { + input_hue += 0.5; + } + + vec4 color = vec4(hsv_to_rgb(vec3(input_hue, 1.0, mod(color_value, 1))), 1.0); + vec2 folded_uv = + uv_warp_fold(in_screen_uv * 2, vec2(0, 0), vec2(1, 1) * folds_coeff); + vec2 inverted_uv = uv_warp_invert(folded_uv, invert_recursive_coords); + vec2 swapped_uv = uv_warp_swap(inverted_uv, swap_recursive_coords); + vec4 last_frame_color = texture2D(last_frame, screen_to_tex(swapped_uv)); + // Give control over how bright the forcibly-mixed color is. + last_frame_color = vec4(min(last_frame_color.rgb * mix_prescale_coeff, 1), 1); + vec4 out_color = mix(color, shift_hue(last_frame_color, shift_hue_coeff), + max(length(color.rgb), force_mix_coeff)); + + if (invert_screen) { + out_color.xyz = vec3(1, 1, 1) - out_color.xyz; + } + gl_FragColor = out_color; } diff --git a/preset/thin_film/thin_film.cc b/preset/thin_film/thin_film.cc index 6b3216e..b90b6ac 100644 --- a/preset/thin_film/thin_film.cc +++ b/preset/thin_film/thin_film.cc @@ -47,6 +47,25 @@ void ThinFilm::OnDrawFrame( auto output_activation = output_render_target->Activate(); thin_film_program_->Use(); + if (SIGINJECT_TRIGGER("invert_screen")) { + invert_screen_ = !invert_screen_; + } + if (SIGINJECT_TRIGGER("invert_hue")) { + invert_hue_ = !invert_hue_; + } + if (SIGINJECT_TRIGGER("invert_coords")) { + invert_coords_ = !invert_coords_; + } + if (SIGINJECT_TRIGGER("invert_recursive_coords")) { + invert_recursive_coords_ = !invert_recursive_coords_; + } + if (SIGINJECT_TRIGGER("swap_coords")) { + swap_coords_ = !swap_coords_; + } + if (SIGINJECT_TRIGGER("swap_recursive_coords")) { + swap_recursive_coords_ = !swap_recursive_coords_; + } + gl::GlBindUniform(thin_film_program_, "pole", UnitVectorAtAngle(energy * 2.0f) / 2.0f); @@ -76,6 +95,20 @@ void ThinFilm::OnDrawFrame( gl::GlBindUniform(thin_film_program_, "folds_coeff", folds_filter_->ProcessSample(SIGINJECT_OVERRIDE( "thin_film_folds_coeff", 0.0f, 0.02f, 1.5f))); + gl::GlBindUniform( + thin_film_program_, "force_mix_coeff", + SIGINJECT_OVERRIDE("thin_film_force_mix_coeff", 0.0f, 0.02f, 1.5f)); + gl::GlBindUniform( + thin_film_program_, "mix_prescale_coeff", + SIGINJECT_OVERRIDE("thin_film_mix_prescale_coeff", 0.0f, 0.0f, 1.5f)); + gl::GlBindUniform(thin_film_program_, "invert_screen", invert_screen_); + gl::GlBindUniform(thin_film_program_, "invert_hue", invert_hue_); + gl::GlBindUniform(thin_film_program_, "invert_coords", invert_coords_); + gl::GlBindUniform(thin_film_program_, "invert_recursive_coords", + invert_recursive_coords_); + gl::GlBindUniform(thin_film_program_, "swap_coords", swap_coords_); + gl::GlBindUniform(thin_film_program_, "swap_recursive_coords", + swap_recursive_coords_); glViewport(0, 0, width(), height()); rectangle_.Draw(); diff --git a/preset/thin_film/thin_film.h b/preset/thin_film/thin_film.h index 22189cd..abbd20a 100644 --- a/preset/thin_film/thin_film.h +++ b/preset/thin_film/thin_film.h @@ -40,6 +40,13 @@ class ThinFilm : public Preset { IirSinglePoleFilter(0.01, IirSinglePoleFilterType::kLowpass); std::shared_ptr folds_filter_ = IirSinglePoleFilter(0.05, IirSinglePoleFilterType::kLowpass); + + bool invert_screen_ = false; + bool invert_hue_ = false; + bool invert_coords_ = false; + bool invert_recursive_coords_ = false; + bool swap_coords_ = false; + bool swap_recursive_coords_ = false; }; } // namespace opendrop From c3fa5742bb2bd487951ca2a60febefce1f9a615f Mon Sep 17 00:00:00 2001 From: Kevin Balke Date: Tue, 4 Oct 2022 11:06:40 -0700 Subject: [PATCH 7/8] Implement fine control over zoom --- configs/midimix.textproto | 29 ++++++++++++++++++++--------- preset/thin_film/thin_film.cc | 9 ++++++--- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/configs/midimix.textproto b/configs/midimix.textproto index ada2e30..1270859 100644 --- a/configs/midimix.textproto +++ b/configs/midimix.textproto @@ -14,6 +14,10 @@ control_mappings { key: "thin_film_folds_coeff" value: "control_change:0:58:0" } +control_mappings { + key: "thin_film_folds_fine_coeff" + value: "control_change:0:59:0" +} control_mappings { key: "thin_film_force_mix_coeff" value: "control_change:0:17:0" @@ -60,6 +64,13 @@ signals_by_name { high: 1.5 } } +signals_by_name { + key: "thin_film_folds_fine_coeff" + value { + low: -0.05 + high: 0.05 + } +} signals_by_name { key: "thin_film_force_mix_coeff" value { @@ -198,15 +209,15 @@ counters_by_name { } controls_by_name { key: "control_change:0:16:0" - value: 0.606299222 + value: 0.11811024 } controls_by_name { key: "control_change:0:17:0" - value: 0.314960629 + value: 0.346456707 } controls_by_name { key: "control_change:0:20:0" - value: 1 + value: 0 } controls_by_name { key: "control_change:0:21:0" @@ -214,7 +225,7 @@ controls_by_name { } controls_by_name { key: "control_change:0:24:0" - value: 0.299212605 + value: 0.338582665 } controls_by_name { key: "control_change:0:25:0" @@ -222,7 +233,7 @@ controls_by_name { } controls_by_name { key: "control_change:0:28:0" - value: 0.937007844 + value: 0.330708653 } controls_by_name { key: "control_change:0:29:0" @@ -238,7 +249,7 @@ controls_by_name { } controls_by_name { key: "control_change:0:50:0" - value: 0.897637784 + value: 0.905511796 } controls_by_name { key: "control_change:0:51:0" @@ -246,7 +257,7 @@ controls_by_name { } controls_by_name { key: "control_change:0:54:0" - value: 0.51968503 + value: 1 } controls_by_name { key: "control_change:0:55:0" @@ -254,9 +265,9 @@ controls_by_name { } controls_by_name { key: "control_change:0:58:0" - value: 0.40157479 + value: 0.299212605 } controls_by_name { key: "control_change:0:59:0" - value: 0.11811024 + value: 0.771653533 } diff --git a/preset/thin_film/thin_film.cc b/preset/thin_film/thin_film.cc index b90b6ac..c6022ba 100644 --- a/preset/thin_film/thin_film.cc +++ b/preset/thin_film/thin_film.cc @@ -92,9 +92,12 @@ void ThinFilm::OnDrawFrame( gl::GlBindUniform( thin_film_program_, "fisheye_coeff", SIGINJECT_OVERRIDE("thin_film_fisheye_coeff", 0.0f, 0.0f, 1.0f)); - gl::GlBindUniform(thin_film_program_, "folds_coeff", - folds_filter_->ProcessSample(SIGINJECT_OVERRIDE( - "thin_film_folds_coeff", 0.0f, 0.02f, 1.5f))); + gl::GlBindUniform( + thin_film_program_, "folds_coeff", + folds_filter_->ProcessSample( + SIGINJECT_OVERRIDE("thin_film_folds_coeff", 0.0f, 0.02f, 1.5f) + + SIGINJECT_OVERRIDE("thin_film_folds_fine_coeff", 0.0f, -0.05f, + 0.05f))); gl::GlBindUniform( thin_film_program_, "force_mix_coeff", SIGINJECT_OVERRIDE("thin_film_force_mix_coeff", 0.0f, 0.02f, 1.5f)); From a60afbcf8916a89a38143148d7435a27ff28e6b7 Mon Sep 17 00:00:00 2001 From: Kevin Balke Date: Tue, 4 Oct 2022 11:07:06 -0700 Subject: [PATCH 8/8] Add Arturia config for thin_film --- configs/arturia.textproto | 363 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 configs/arturia.textproto diff --git a/configs/arturia.textproto b/configs/arturia.textproto new file mode 100644 index 0000000..d517f5d --- /dev/null +++ b/configs/arturia.textproto @@ -0,0 +1,363 @@ +buttons: 1 +buttons: 4 +buttons: 7 +buttons: 9 +buttons: 10 +buttons: 13 +buttons: 16 +buttons: 19 +buttons: 64 +buttons: 65 +buttons: 66 +buttons: 67 +buttons: 68 +buttons: 69 +control_mappings { + key: "thin_film_fisheye_coeff" + value: "control_change:0:93:0" +} +control_mappings { + key: "thin_film_folds_coeff" + value: "control_change:0:75:0" +} +control_mappings { + key: "thin_film_folds_fine_coeff" + value: "control_change:0:72:0" +} +control_mappings { + key: "thin_film_force_mix_coeff" + value: "control_change:0:114:0" +} +control_mappings { + key: "thin_film_min_value_coeff" + value: "control_change:0:77:0" +} +control_mappings { + key: "thin_film_mix_prescale_coeff" + value: "control_change:0:18:0" +} +control_mappings { + key: "thin_film_phase_x_coeff" + value: "control_change:0:74:0" +} +control_mappings { + key: "thin_film_phase_y_coeff" + value: "control_change:0:71:0" +} +control_mappings { + key: "thin_film_ripple_hue" + value: "control_change:0:76:0" +} +control_mappings { + key: "thin_film_rotate_coeff" + value: "control_change:0:10:0" +} +control_mappings { + key: "thin_film_shift_hue_coeff" + value: "control_change:0:73:0" +} +signals_by_name { + key: "thin_film_fisheye_coeff" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_folds_coeff" + value { + low: 0.02 + high: 1.5 + } +} +signals_by_name { + key: "thin_film_folds_fine_coeff" + value { + low: -0.05 + high: 0.05 + } +} +signals_by_name { + key: "thin_film_force_mix_coeff" + value { + low: 0.02 + high: 1.5 + } +} +signals_by_name { + key: "thin_film_min_value_coeff" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_mix_prescale_coeff" + value { + low: 0 + high: 1.5 + } +} +signals_by_name { + key: "thin_film_phase_x_coeff" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_phase_y_coeff" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_ripple_hue" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_rotate_coeff" + value { + low: 0 + high: 1 + } +} +signals_by_name { + key: "thin_film_shift_hue_coeff" + value { + low: 0 + high: 1 + } +} +button_mappings { + key: "invert_coords" + value: 66 +} +button_mappings { + key: "invert_hue" + value: 65 +} +button_mappings { + key: "invert_recursive_coords" + value: 67 +} +button_mappings { + key: "invert_screen" + value: 64 +} +button_mappings { + key: "swap_coords" + value: 68 +} +button_mappings { + key: "swap_recursive_coords" + value: 69 +} +counters_by_name { + key: "invert_coords" + value { + low: 0 + high: 0 + value: 0 + } +} +counters_by_name { + key: "invert_hue" + value { + low: 0 + high: 0 + value: 0 + } +} +counters_by_name { + key: "invert_recursive_coords" + value { + low: 0 + high: 0 + value: 0 + } +} +counters_by_name { + key: "invert_screen" + value { + low: 0 + high: 0 + value: 0 + } +} +counters_by_name { + key: "next_preset" + value { + low: 0 + high: 0 + value: 0 + } +} +counters_by_name { + key: "swap_coords" + value { + low: 0 + high: 0 + value: 0 + } +} +counters_by_name { + key: "swap_recursive_coords" + value { + low: 0 + high: 0 + value: 0 + } +} +controls_by_name { + key: "control_change:0:10:0" + value: 0.779527545 +} +controls_by_name { + key: "control_change:0:114:0" + value: 0.606299222 +} +controls_by_name { + key: "control_change:0:16:0" + value: 0.22047244 +} +controls_by_name { + key: "control_change:0:17:0" + value: 0.511811 +} +controls_by_name { + key: "control_change:0:18:0" + value: 0.740157485 +} +controls_by_name { + key: "control_change:0:20:0" + value: 0.535433054 +} +controls_by_name { + key: "control_change:0:21:0" + value: 0.732283473 +} +controls_by_name { + key: "control_change:0:24:0" + value: 0.496063 +} +controls_by_name { + key: "control_change:0:25:0" + value: 0.51968503 +} +controls_by_name { + key: "control_change:0:28:0" + value: 0.51968503 +} +controls_by_name { + key: "control_change:0:29:0" + value: 0.511811 +} +controls_by_name { + key: "control_change:0:46:0" + value: 0.496063 +} +controls_by_name { + key: "control_change:0:47:0" + value: 0.456692904 +} +controls_by_name { + key: "control_change:0:48:0" + value: 0.267716527 +} +controls_by_name { + key: "control_change:0:49:0" + value: 0 +} +controls_by_name { + key: "control_change:0:50:0" + value: 0.51968503 +} +controls_by_name { + key: "control_change:0:51:0" + value: 0.511811 +} +controls_by_name { + key: "control_change:0:54:0" + value: 0.496063 +} +controls_by_name { + key: "control_change:0:55:0" + value: 0.496063 +} +controls_by_name { + key: "control_change:0:58:0" + value: 0.496063 +} +controls_by_name { + key: "control_change:0:59:0" + value: 0.503937 +} +controls_by_name { + key: "control_change:0:71:0" + value: 0.448818892 +} +controls_by_name { + key: "control_change:0:72:0" + value: 0.0866141766 +} +controls_by_name { + key: "control_change:0:73:0" + value: 0.0393700786 +} +controls_by_name { + key: "control_change:0:74:0" + value: 0.22047244 +} +controls_by_name { + key: "control_change:0:75:0" + value: 0.354330719 +} +controls_by_name { + key: "control_change:0:76:0" + value: 0.897637784 +} +controls_by_name { + key: "control_change:0:77:0" + value: 1 +} +controls_by_name { + key: "control_change:0:79:0" + value: 1 +} +controls_by_name { + key: "control_change:0:7:0" + value: 0.708661437 +} +controls_by_name { + key: "control_change:0:93:0" + value: 0 +} +controls_by_name { + key: "polytouch:0:0:64" + value: 0.00787401572 +} +controls_by_name { + key: "polytouch:0:0:65" + value: 0.00787401572 +} +controls_by_name { + key: "polytouch:0:0:66" + value: 0.00787401572 +} +controls_by_name { + key: "polytouch:0:0:67" + value: 0.00787401572 +} +controls_by_name { + key: "polytouch:0:0:68" + value: 0.00787401572 +} +controls_by_name { + key: "polytouch:0:0:69" + value: 0.00787401572 +}