Add CMYKHalftone, LumaSobel, DropShadow and segmented waves

This commit is contained in:
Edwin Jakobs
2020-02-09 22:50:08 +01:00
parent 61507b525f
commit 95eecc150c
10 changed files with 369 additions and 4 deletions

View File

@@ -4,6 +4,7 @@ import org.openrndr.draw.*
import org.openrndr.extra.fx.filterFragmentCode import org.openrndr.extra.fx.filterFragmentCode
import org.openrndr.extra.parameters.Description import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.extra.parameters.IntParameter
@Description("Horizontal wave") @Description("Horizontal wave")
class HorizontalWave : Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("distort/horizontal-wave.frag"))) { class HorizontalWave : Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("distort/horizontal-wave.frag"))) {
@@ -16,10 +17,15 @@ class HorizontalWave : Filter(Shader.createFromCode(filterVertexCode, filterFrag
@DoubleParameter("phase", -0.5, 0.5) @DoubleParameter("phase", -0.5, 0.5)
var phase: Double by parameters var phase: Double by parameters
@IntParameter("segments", 0, 256)
var segments: Int by parameters
init { init {
frequency = 1.0 frequency = 1.0
amplitude = 0.1 amplitude = 0.1
phase = 0.0 phase = 0.0
segments = 0
} }
var bicubicFiltering = true var bicubicFiltering = true
@@ -43,10 +49,15 @@ class VerticalWave : Filter(Shader.createFromCode(filterVertexCode, filterFragme
@DoubleParameter("phase", -0.5, 0.5) @DoubleParameter("phase", -0.5, 0.5)
var phase: Double by parameters var phase: Double by parameters
@IntParameter("segments", 0, 256)
var segments: Int by parameters
init { init {
frequency = 1.0 frequency = 1.0
amplitude = 0.1 amplitude = 0.1
phase = 0.0 phase = 0.0
segments = 0
} }
var bicubicFiltering = true var bicubicFiltering = true
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) { override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {

View File

@@ -0,0 +1,27 @@
package org.openrndr.extra.fx.dither
import org.openrndr.draw.Filter
import org.openrndr.draw.Shader
import org.openrndr.extra.fx.filterFragmentCode
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
@Description("CMYK Halftone")
class CMYKHalftone: Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("dither/cmyk-halftone.frag"))) {
@DoubleParameter("scale", 1.0, 30.0, precision = 4)
var scale: Double by parameters
@DoubleParameter("dotSize", 1.0, 3.0, precision = 4)
var dotSize: Double by parameters
@DoubleParameter("rotation", -180.0, 180.0)
var rotation: Double by parameters
init {
scale = 3.0
rotation = 0.0
dotSize = 1.0
}
}

View File

@@ -0,0 +1,32 @@
package org.openrndr.extra.fx.edges
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.Filter
import org.openrndr.draw.Shader
import org.openrndr.extra.fx.filterFragmentCode
import org.openrndr.extra.parameters.ColorParameter
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
@Description("Luma threshold ")
class LumaSobel : Filter(Shader.createFromCode(Filter.filterVertexCode, filterFragmentCode("edges/luma-sobel.frag"))) {
@ColorParameter("background color")
var backgroundColor: ColorRGBa by parameters
@ColorParameter("edge color")
var edgeColor: ColorRGBa by parameters
@DoubleParameter("background opacity", 0.0, 1.0)
var backgroundOpacity:Double by parameters
@DoubleParameter("edge opacity", 0.0, 1.0)
var edgeOpacity:Double by parameters
init {
backgroundColor = ColorRGBa.BLACK
edgeColor = ColorRGBa.WHITE
edgeOpacity = 1.0
backgroundOpacity = 1.0
}
}

View File

@@ -0,0 +1,71 @@
package org.openrndr.extra.fx.shadow
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.*
import org.openrndr.extra.fx.filterFragmentCode
import org.openrndr.extra.parameters.ColorParameter
import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.extra.parameters.IntParameter
import org.openrndr.math.Vector2
import org.openrndr.resourceUrl
private class Blend: Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("shadow/dropshadow-blend.frag"))) {
var shift: Vector2 by parameters
}
@Description("Drop shadow")
class DropShadow : Filter(Shader.createFromCode(filterVertexCode, filterFragmentCode("shadow/dropshadow-blur.frag"))) {
@IntParameter("blur window", 1, 25)
var window: Int by parameters
var spread: Double by parameters
@DoubleParameter("gain", 0.0, 4.0)
var gain: Double by parameters
var shift: Vector2 = Vector2.ZERO
@ColorParameter("color")
var color: ColorRGBa by parameters
private var intermediate: ColorBuffer? = null
private var intermediate2: ColorBuffer? = null
private var b = Blend()
init {
color = ColorRGBa.BLACK
window = 5
spread = 1.0
gain = 1.0
}
override fun apply(source: Array<ColorBuffer>, target: Array<ColorBuffer>) {
intermediate?.let {
if (it.width != target[0].width || it.height != target[0].height) {
intermediate = null
}
}
intermediate2?.let {
if (it.width != target[0].width || it.height != target[0].height) {
intermediate2 = null
}
}
if (intermediate == null) {
intermediate = colorBuffer(target[0].width, target[0].height, target[0].contentScale, target[0].format, target[0].type)
}
if (intermediate2 == null) {
intermediate2 = colorBuffer(target[0].width, target[0].height, target[0].contentScale, target[0].format, target[0].type)
}
intermediate?.let {
parameters["blurDirection"] = Vector2(1.0, 0.0)
super.apply(source, arrayOf(it))
parameters["blurDirection"] = Vector2(0.0, 1.0)
super.apply(arrayOf(it), arrayOf(intermediate2!!))
b.shift = shift / Vector2(target[0].width * 1.0, target[0].height * 1.0)
b.apply(arrayOf(intermediate2!!, source[0]), target)
}
}
}

View File

@@ -7,11 +7,25 @@ uniform float amplitude;
uniform float frequency; uniform float frequency;
out vec4 o_color; out vec4 o_color;
uniform int segments;
float truncate(float x, int segments) {
if (segments == 0) {
return x;
} else {
return floor(x*segments) / segments;
}
}
void main() { void main() {
vec2 uv = v_texCoord0; vec2 uv = v_texCoord0;
uv.x += amplitude * cos(uv.y * 3.1415926535 * frequency + phase * 3.1415926535); uv.x += amplitude * cos(truncate(uv.y, segments) * 3.1415926535 * frequency + phase * 3.1415926535);
if (uv.x >= 0.0 && uv.x < 1.0) { if (uv.x >= 0.0 && uv.x < 1.0) {
o_color = texture(tex0, uv); if (segments == 0) {
o_color = texture(tex0, uv);
} else {
o_color = textureLod(tex0, uv, 0.0);
}
} else { } else {
o_color = vec4(0.0); o_color = vec4(0.0);
} }

View File

@@ -7,11 +7,25 @@ uniform float amplitude;
uniform float frequency; uniform float frequency;
out vec4 o_color; out vec4 o_color;
uniform int segments;
float truncate(float x, int segments) {
if (segments == 0) {
return x;
} else {
return floor(x*segments) / segments;
}
}
void main() { void main() {
vec2 uv = v_texCoord0; vec2 uv = v_texCoord0;
uv.y += amplitude * sin(uv.x * 3.1415926535 * frequency + phase * 3.1415926535); uv.y += amplitude * sin(truncate(uv.x, segments) * 3.1415926535 * frequency + phase * 3.1415926535);
if (uv.y >= 0.0 && uv.y < 1.0) { if (uv.y >= 0.0 && uv.y < 1.0) {
o_color = texture(tex0, uv); if (segments == 0) {
o_color = texture(tex0, uv);
} else {
o_color = textureLod(tex0, uv, 0.0);
}
} else { } else {
o_color = vec4(0.0); o_color = vec4(0.0);
} }

View File

@@ -0,0 +1,101 @@
/* Based on CMYK Halftone by tsone https://www.shadertoy.com/view/Mdf3Dn
*/
#version 330 core
uniform float dotSize;
#define SST 0.888
#define SSQ 0.288
uniform float scale;
uniform float rotation;
in vec2 v_texCoord0;
uniform sampler2D tex0;
out vec4 o_color;
vec4 rgb2cmyki(in vec3 c)
{
float k = max(max(c.r, c.g), c.b);
return min(vec4(c.rgb / k, k), 1.0);
}
vec3 cmyki2rgb(in vec4 c)
{
return c.rgb * c.a;
}
vec3 u(vec4 c) {
if (c.a == 0) {
return vec3(0.0);
} else {
return c.rgb/c.a;
}
}
vec4 cmyki2rgba(in vec4 cmyk){
vec4 c = vec4(0.0, 1.0, 1.0, 1.0)*(1.0-cmyk.r);
vec4 m = vec4(1.0, 0.0, 1.0, 1.0)*(1.0-cmyk.g);
vec4 y = vec4(1.0, 1.0, 0.0, 1.0)*(1.0-cmyk.b);
vec4 k = vec4(0.0, 0.0, 0.0, 1.0)*(1.0-cmyk.a);
vec4 f = c;
f = (1.0-f.a) * m + f.a * vec4(u(f)*u(m),1.0) * m.a + (1.0-m.a) * f;
f = (1.0-f.a) * y + f.a * vec4(u(f)*u(y),1.0) * y.a + (1.0-y.a) * f;
f = (1.0-f.a) * k + f.a * vec4(u(f)*u(k),1.0) * k.a + (1.0-k.a) * f;
return f;
}
vec2 px2uv(in vec2 px)
{
return vec2(px / textureSize(tex0, 0));
}
vec2 grid(in vec2 px)
{
return px - mod(px, scale);
}
vec4 ss(in vec4 v)
{
return smoothstep(vec4(SST-SSQ), vec4(SST+SSQ), v);
}
vec4 halftone(in vec2 fc,in mat2 m)
{
vec2 smp = (grid(m*fc) + 0.5*scale) * m;
float s = min(length(fc-smp) / (dotSize*0.5*scale), 1.0);
vec3 texc = texture(tex0, px2uv(smp+textureSize(tex0, 0)/2.0)).rgb;
vec4 c = rgb2cmyki(texc);
return c+s;
}
mat2 rotm(in float r)
{
float cr = cos(r);
float sr = sin(r);
return mat2(
cr,-sr,
sr,cr
);
}
void main() {
vec2 fc = v_texCoord0 * textureSize(tex0, 0) - textureSize(tex0, 0)/2.0;
mat2 mc = rotm(rotation + radians(15.0));
mat2 mm = rotm(rotation + radians(75.0));
mat2 my = rotm(rotation);
mat2 mk = rotm(rotation + radians(45.0));
float k = halftone(fc, mk).a;
vec4 c = cmyki2rgba(ss(vec4(
halftone(fc, mc).r,
halftone(fc, mm).g,
halftone(fc, my).b,
halftone(fc, mk).a
)));
o_color = c;
}

View File

@@ -0,0 +1,49 @@
#version 330 core
in vec2 v_texCoord0;
uniform sampler2D tex0;
uniform vec4 backgroundColor;
uniform vec4 edgeColor;
uniform float backgroundOpacity;
uniform float edgeOpacity;
out vec4 o_color;
float step = 1.0;
float luma(vec4 color){
vec3 n = color.a == 0.0? vec3(0.0) : color.rgb/color.a;
return dot(n, vec3(1.0/3.0));
}
void main() {
vec2 step = 1.0 / textureSize(tex0, 0);
float tl = luma(texture(tex0, v_texCoord0 + vec2(-step.x, step.y)));
float l = luma(texture(tex0, v_texCoord0 + vec2(-step.x, 0)));
float bl = luma(texture(tex0, v_texCoord0 + vec2(-step.x, -step.y)));
float t = luma(texture(tex0, v_texCoord0 + vec2(0, step.y)));
float b = luma(texture(tex0, v_texCoord0 + vec2(0, -step.y)));
float tr = luma(texture(tex0, v_texCoord0 + vec2(step.x, step.y)));
float r = luma(texture(tex0, v_texCoord0 + vec2(step.x, 0)));
float br = luma(texture(tex0, v_texCoord0 + vec2(step.x, -step.y)));
// Sobel masks (see http://en.wikipedia.org/wiki/Sobel_operator)
// 1 0 -1 -1 -2 -1
// X = 2 0 -2 Y = 0 0 0
// 1 0 -1 1 2 1
// You could also use Scharr operator:
// 3 0 -3 3 10 3
// X = 10 0 -10 Y = 0 0 0
// 3 0 -3 -3 -10 -3
float x = tl + 2.0 * l + bl - tr - 2.0 * r - br;
float y = -tl - 2.0 * t - tr + bl + 2.0 * b + br;
float intensity = sqrt((x*x) + (y*y)) / sqrt(2);
vec4 color = mix(vec4(backgroundColor.rgb, backgroundOpacity), vec4(edgeColor.rgb, edgeOpacity), intensity);
vec4 a = texture(tex0, v_texCoord0);
o_color = vec4(color.rgb, 1.0) * color.a * a.a;
}

View File

@@ -0,0 +1,14 @@
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform vec2 shift;
out vec4 o_color;
void main() {
vec4 a = texture(tex0, v_texCoord0-shift);
vec4 b = texture(tex1, v_texCoord0);
float alpha = min(1,max(0, b.a));
o_color = a * (1.0-alpha) + b;
}

View File

@@ -0,0 +1,32 @@
// openrndr - gl3 - box-blur
#version 330
in vec2 v_texCoord0;
uniform sampler2D tex0;
uniform vec2 blurDirection;
uniform int window;
uniform float sigma;
uniform float gain;
uniform vec4 subtract;
uniform float spread;
uniform vec4 color;
out vec4 o_color;
void main() {
vec2 s = textureSize(tex0, 0).xy;
s = vec2(1.0/s.x, 1.0/s.y);
int w = window;
vec4 sum = vec4(0, 0, 0, 0);
float weight = 0;
for (int x = -w; x<= w; ++x) {
float lw = 1.0;
sum += texture(tex0, v_texCoord0 + x * blurDirection * s * spread);
weight += lw;
}
o_color = (sum / weight) * gain;
o_color.rgb = color.rgb * o_color.a;
}