Skip to content

Instantly share code, notes, and snippets.

@mds2
Created January 9, 2021 06:43
Show Gist options
  • Save mds2/6ee6d8bbed2416404114f2253e9d397b to your computer and use it in GitHub Desktop.
Save mds2/6ee6d8bbed2416404114f2253e9d397b to your computer and use it in GitHub Desktop.
#version 100
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texcoord;
uniform sampler2D tex;
uniform float time;
uniform float width;
uniform float height;
const float EDGE_OR_CORNER_DETECT = 0.1; // 0 for corner, 1 for edge
const float WINDOW_WIDTH = 4.0; // max 6.0
const float SHOW_BACKGROUND = 0.25;
// 0.0 for no background, 1.0 for all background
const vec2 webcam_resolution = vec2(320.0, 240.0);
float iTime;
vec2 iResolution;
float hash12(vec2 x)
{
return mod(13.3 + 201.1 * sin(302.2 * x.x + 123.7 * x.y + 11.1), 1.0);
}
float noise_term(in vec2 x, in float scale_val) {
vec2 s = vec2(scale_val);
vec2 x00 = x - mod(x, s);
vec2 x01 = x + vec2(0.0, scale_val);
x01 = x01 - mod(x01, s);
vec2 x10 = x + vec2(scale_val, 0.0);
x10 = x10 - mod(x10, s);
vec2 x11 = x + s;
x11 = x11 - mod(x11, s);
float v00 = hash12(x00);
float v01 = hash12(x01);
float v10 = hash12(x10);
float v11 = hash12(x11);
vec2 uv = mod(x, s) / s;
float yweight = smoothstep(0.0, 1.0, uv.y);
float v1 = mix(v10, v11, yweight);
float v0 = mix(v00, v01, yweight);
float xweight = smoothstep(0.0, 1.0, uv.x);
return mix(v0, v1, xweight);
}
float noise(in vec2 x, in float base_scale, in float space_decay, in float height_decay,
in float shift_by) {
float h = 1.0;
float s = base_scale;
float summation = 0.0;
for (int i = 0; i < 4; ++i) {
summation = summation + h * noise_term(x + vec2(0.0, s * shift_by), s);
s *= space_decay;
h *= height_decay;
}
return summation;
}
float simple_noise(in vec2 uv, in float shift_by) {
return noise(uv * 10.0, 5.0, 0.75, 0.75, shift_by);
}
vec2 noise2(in vec2 uv, in float shift_by) {
return vec2(simple_noise(uv, shift_by),
simple_noise(uv + vec2(0.0, 101.0), shift_by));
}
vec3 YUV(in vec2 fragCoord) {
const mat3 to_yuvish = mat3(0.299, -0.14713, 0.615,
0.587, -0.28886, -0.51499,
0.114, 0.436, -0.10001);
return to_yuvish * texture2D(tex, fragCoord / iResolution.xy).rgb;
}
float Yval(in vec2 fragCoord) {
return YUV(fragCoord).x;
}
vec4 mainImage(in vec2 fragCoord )
{
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = fragCoord/iResolution.xy;
mat2 M = mat2(0.0);
vec2 scale = iResolution.xy / min(iResolution.xy, webcam_resolution.xy);
scale *= 1.5;
vec2 off = vec2(-4.0);
for (int i = 0; i < 9; ++i) {
off.y = -4.0;
off.x += 1.0;
for (int j = 0; j < 9; ++j) {
off.y += 1.0;
float weight = smoothstep(WINDOW_WIDTH, 0.0, length(off));
float Ix = 0.5 * (Yval(fragCoord + scale * (off + vec2(1.0, 0.0))) -
Yval(fragCoord + scale * (off - vec2(1.0, 0.0))));
float Iy = 0.5 * (Yval(fragCoord + scale * (off + vec2(0.0, 1.0))) -
Yval(fragCoord + scale * (off - vec2(0.0, 1.0))));
M += weight * mat2(Ix * Ix, Ix * Iy, Ix * Iy, Iy * Iy);
}
}
// mat2 M = mat2(Ix * Ix, Ix * Iy, Ix * Iy, Iy * Iy);
float A = 1.0;
float B = -M[0][0] - M[1][1];
float C = M[0][0] * M[1][1] - M[0][1] * M[1][0];
float l1 = (-B + sqrt(B * B - 4.0 * A * C)) / (2.0 * A);
float l2 = (-B - sqrt(B * B - 4.0 * A * C)) / (2.0 * A);
float min_eig = min(abs(l1), abs(l2));
float max_eig = max(abs(l1), abs(l2));
// float min_eig = min(l1, l2);
float eig_to_use = mix(min_eig, max_eig, EDGE_OR_CORNER_DETECT);
// Time varying pixel color
vec3 col = smoothstep(vec3(0.0), 0.5 * vec3(0.1, 0.2, 0.3), vec3(eig_to_use));
vec3 raw_color = texture2D(tex, fragCoord / iResolution.xy).rgb;
const float speed = 10.0;
float time = speed * iTime;
uv = -(2.0 * fragCoord -iResolution.xy) / iResolution.y;
// Time varying pixel color
vec2 flame_col = noise2(uv + noise2(1.5 * uv + noise2(2.0 * uv, -0.2 * time), -0.13 * time), -0.1 * time) - 0.75;
flame_col.g = min(0.5 * flame_col.g, flame_col.r);
flame_col *= smoothstep(-0.25, -0.5, uv.y - 0.2 + flame_col.r - 1.0 * min(1.0, uv.x * uv.x));
raw_color = vec3(0.8, 0.8, 1.5) * raw_color + 0.1;
// Output to screen
return vec4(
mix(mix(raw_color, col, 1.0 - SHOW_BACKGROUND),
vec3(flame_col, 0.0),
flame_col.r),
1.0);
}
void main()
{
iTime = time;
iResolution = vec2(width, height);
vec2 fragCoord = vec2(v_texcoord.x, 1.0 - v_texcoord.y) *
vec2(width, height);
fragCoord = iResolution - fragCoord;
gl_FragColor = mainImage(fragCoord);
}
# run this one *after* running setup_virtual_webcam.sh
# it will require a variety of gstreamer plugins
# it will also take over your main webcam.
# Kill the process(es) this launches to regain control of your main webcam
gst-launch-1.0 --gst-debug -v v4l2src device=/dev/video0 ! video/x-raw,width=640,height=360 ! videoconvert ! video/x-raw,format=RGBA ! glupload ! glshader fragment="\"`cat demon.frag`\"" ! gldownload ! video/x-raw,width=1280,height=720 ! queue ! videoconvert ! video/x-raw,format=I420,framerate=30/1 ! v4l2sink device=/dev/video10
# launch this one first.
# it will require first installing v4l2loopback
# getting that working properly might be tricky
sudo modprobe v4l2loopback video_nr="10" 'card_label=virtcam' exclusive_caps=1 max_buffers=2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment