From a048f4bdbdb3afe2f5114684b2d10d153293ac8a Mon Sep 17 00:00:00 2001 From: Vladimir Almonte Date: Wed, 12 Jan 2022 20:49:54 +0100 Subject: [PATCH] New Nodes 4 new node: Masked blur ray swirl cuervature --- src/lib/library/libraryv2.ts | 16 +++++- src/lib/library/v3/curvature.ts | 94 ++++++++++++++++++++++++++++++++ src/lib/library/v3/maskedblur.ts | 69 +++++++++++++++++++++++ src/lib/library/v3/rays.ts | 31 +++++++++++ src/lib/library/v3/swirl.ts | 39 +++++++++++++ 5 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 src/lib/library/v3/curvature.ts create mode 100644 src/lib/library/v3/maskedblur.ts create mode 100644 src/lib/library/v3/rays.ts create mode 100644 src/lib/library/v3/swirl.ts diff --git a/src/lib/library/libraryv2.ts b/src/lib/library/libraryv2.ts index dae2dbc..c4a3df8 100644 --- a/src/lib/library/libraryv2.ts +++ b/src/lib/library/libraryv2.ts @@ -73,6 +73,13 @@ import { GradientNoiseFractalSum } from "./v2/gradientnoisefractalsum"; import { SimplexNoiseV2 } from "./v2/simplexnoise"; import { DirectionalWarpNodeV2 } from "./v2/directionalwarpv2"; import { ImageNode } from "./v2/imagenode"; +import { MaskedBlur } from "./v3/maskedblur"; +import { Rays } from "./v3/rays"; +import { Swirl } from "./v3/swirl"; +import { Curvature} from "./v3/curvature"; +import { Pixelate } from "./v3/pixelate"; +import { CausticsNoise } from "./v3/causticsnoise"; +import { TilePath } from "./v3/tilepath"; export function createLibrary() { const lib = new DesignerLibrary(); @@ -183,6 +190,13 @@ export function createLibrary() { lib.addNode("image", "Image", ImageNode); //lib.addNode("simplexnoise", "Simplex Noise", SimplexNoiseV2); // lib.addNode("betterwarp", "Better Warp", BetterWarpNode); - + lib.addNode("maskedblur", "Masked Blur", MaskedBlur); + lib.addNode("ray","Ray", Rays) + lib.addNode("swirl", "Swirl", Swirl); + lib.addNode("curvature", "Curvature", Curvature); + //lib.addNode("causticsnoise", "Caustics Noise", CausticsNoise); + //lib.addNode("pixelate", "Pixelate", Pixelate); + //lib.addNode("tilepath", "Tile Path", TilePath); + return lib; } diff --git a/src/lib/library/v3/curvature.ts b/src/lib/library/v3/curvature.ts new file mode 100644 index 0000000..5825e6b --- /dev/null +++ b/src/lib/library/v3/curvature.ts @@ -0,0 +1,94 @@ +import { GpuDesignerNode } from "../../designer/gpudesignernode"; + +//https://www.shadertoy.com/view/3dKczy +export class Curvature extends GpuDesignerNode{ + public init() { + this.title = "Curvature"; + + this.addInput("height");//height + + this.addEnumProperty("type", "Type", [ + "Mix curvature", + "Sharp curvature", + "Medium curvature", + "Smooth curvature" + ]); + + this.addFloatProperty("intensity", "Intensity", 1, 0, 2, 0.1); + this.addFloatProperty("angle", "Angle", 0.5, -1.0, 1, 0.1); + this.addFloatProperty("samples", "Samples", 4, 0, 12, 1); + + const advancedProps = this.createGroup("Advanced properties"); + advancedProps.collapsed = false; + advancedProps.add( + this.addFloatProperty("sh_c", "Sharp Curvature", 0.5, 0.0, 1, 0.1) + ); + advancedProps.add( + this.addFloatProperty("me_c", "Mediun Curvature", 1.5, 0.0, 3, 0.1) + ); + + advancedProps.add( + this.addFloatProperty("sm_c", "Smooth Curvature", 3.0, 0.0, 4, 0.1) + ); + + + const source = ` + float HeightMap( vec2 p ){ + return texture(height, p).x; + } + float Curve( vec2 p, vec2 o ){ + float a = HeightMap(p+o); + float b = HeightMap(p-o); + return -a - b; + } + float CurvatureMap( vec2 p, float r ){ + float q = prop_samples; // sample quality + float s = r/q; + float H = HeightMap(p)*2.0; + float v = 0.0; + vec2 o; + for( o.x = -q; o.x < q; o.x++ ) + for( o.y = -q; o.y < q; o.y++ ){ + float c = Curve(p, o*s); + v += (H + c) * ((r-length(o*s)) / r); + } + return v/(q*q); + } + + vec4 process(vec2 uv) + { + if (!height_connected) + return vec4(0,0,0,1.0); + + vec4 color = texture(height,uv); + float i = prop_intensity; //Intesity + + float c; + + switch (prop_type) { + case 0: //Mix curvature + c += CurvatureMap(uv, i*prop_sh_c*0.01)*8.0; // sharp curvature + c += CurvatureMap(uv, i*prop_me_c*0.01)*3.0; // medium + c += CurvatureMap(uv, i*prop_sm_c*0.01)*1.5; // smooth curvature + break; + case 1: //Sharp curvature + c += CurvatureMap(uv, i*prop_sh_c*0.01)*8.0; // sharp curvature + break; + case 2: //Medium curvature + c += CurvatureMap(uv, i*prop_me_c*0.01)*3.0; // medium + break; + case 3: //Smooth curvature + c += CurvatureMap(uv, i*prop_sm_c*0.01)*1.5; // smooth curvature + break; + } + color.rgb = vec3( prop_angle + c ); + color.a = 1.0; + + return color; + } + `; + + this.buildShader(source); + } + +} \ No newline at end of file diff --git a/src/lib/library/v3/maskedblur.ts b/src/lib/library/v3/maskedblur.ts new file mode 100644 index 0000000..de5d0d2 --- /dev/null +++ b/src/lib/library/v3/maskedblur.ts @@ -0,0 +1,69 @@ +import { GpuDesignerNode } from "../../designer/gpudesignernode"; + +// uses single pass gaussian +// https://www.shadertoy.com/view/4tSyzy +// https://stackoverflow.com/questions/2157920/why-define-pi-4atan1-d0 +export class MaskedBlur extends GpuDesignerNode { + public init() { + this.title = "Masked Blur"; + + this.addInput("image"); + this.addInput("mask"); + + this.addFloatProperty("intensity", "Intensity", 1, 0, 10, 0.1); + this.addIntProperty("samples", "Samples", 50, 0, 100, 1); + this.addFloatProperty("opacity", "Opacity", 0.5, 0.0, 1.0, 0.01); + + + + const source = ` + #define pow2(x) (x * x) + + const float pi = atan(1.0) * 4.0; + + float gaussian(vec2 i, float sigma) { + return 1.0 / (2.0 * pi * pow2(sigma)) * exp(-((pow2(i.x) + pow2(i.y)) / (2.0 * pow2(sigma)))); + } + + vec3 blur(sampler2D sp, vec2 uv, vec2 scale) { + vec3 col = vec3(0.0); + float accum = 0.0; + float weight; + vec2 offset; + + float sigma = float(prop_samples) * 0.25; + + for (int x = -prop_samples / 2; x < prop_samples / 2; ++x) { + for (int y = -prop_samples / 2; y < prop_samples / 2; ++y) { + offset = vec2(x, y); + weight = gaussian(offset, sigma); + col += texture(sp, uv + scale * offset).rgb * weight; + accum += weight; + } + } + + return col / accum; + } + + vec4 process(vec2 uv) + { + float finalMask = 1.0-texture(mask, uv).r; + float finalOpacity = prop_opacity; + + if (!image_connected) + return vec4(0,0,0,1.0); + + vec4 color = vec4(0.0); + vec2 ps = vec2(1.0, 1.0) / _textureSize; + color.rgb = blur(image, uv, ps * prop_intensity * (1.0 - (finalMask*finalOpacity)) ); + color.a = 1.0; + + //finalOpacity + + return color; + } + `; + + this.buildShader(source); + } +} diff --git a/src/lib/library/v3/rays.ts b/src/lib/library/v3/rays.ts new file mode 100644 index 0000000..45be62a --- /dev/null +++ b/src/lib/library/v3/rays.ts @@ -0,0 +1,31 @@ +import { GpuDesignerNode } from "../../designer/gpudesignernode"; + +export class Rays extends GpuDesignerNode { + public init() { + this.title = "Ray"; + + this.addIntProperty("sides", "Side", 3, 1, 10, 1); + this.addFloatProperty("angle", "Angle", 0, 0.0, 360.0, 1); + this.addFloatProperty("translateX", "Translate X", 0.5, 0.0, 1.0, 0.01); + this.addFloatProperty("translateY", "Translate Y", 0.5, 0.0, 1.0, 0.01); + + const source = ` + vec4 process(vec2 uv) + { + #define PI 3.14159265359 + + uv = uv - vec2(prop_translateX,prop_translateY); + + vec2 p = vec2(0) - uv; + float r = length(p); + float a = atan(uv.x,uv.y)+radians(prop_angle); + float n = float(prop_sides); // n, number of sides + float shape = sin(r*PI)*0.5+0.5; + shape = sin(a*n); + return vec4(vec3(shape),1.0); + } + `; + + this.buildShader(source); + } +} \ No newline at end of file diff --git a/src/lib/library/v3/swirl.ts b/src/lib/library/v3/swirl.ts new file mode 100644 index 0000000..724fe4c --- /dev/null +++ b/src/lib/library/v3/swirl.ts @@ -0,0 +1,39 @@ +import { GpuDesignerNode } from "../../designer/gpudesignernode"; + +//https://www.shadertoy.com/view/Xscyzn +export class Swirl extends GpuDesignerNode { + public init() { + this.title = "Swirl"; + + this.addInput("image"); + + this.addFloatProperty("radius", "Radius", 0.7, 0, 1, 0.01); + this.addFloatProperty("angle", "Angle", 90, 0.0, 360.0, 0.1); + + const source = ` + #define PI 3.14159265359 + + vec4 process(vec2 uv) //(vec2 uv) + { + if (!image_connected) + return vec4(0,0,0,1.0); + + float effectRadius = prop_radius; + float effectAngle = radians(prop_angle); + + vec2 center = vec2(0) - uv; + center = center == vec2(0., 0.) ? vec2(.5, .5) : center; + + uv = uv - vec2(1) - center; + + float len = length(uv); + float angle = atan(uv.y, uv.x) + effectAngle * smoothstep(effectRadius, 0.0, len); + float radius = length(uv); + + return texture(image, vec2(radius * cos(angle), radius * sin(angle)) + center); + } + `; + + this.buildShader(source); + } +}