diff --git a/docs/src/shader-defs/spiral-def.ts b/docs/src/shader-defs/spiral-def.ts index 50e4f86ef..00f735d52 100644 --- a/docs/src/shader-defs/spiral-def.ts +++ b/docs/src/shader-defs/spiral-def.ts @@ -50,10 +50,11 @@ export const spiralDef: ShaderDef = { { name: 'strokeTaper', type: 'number', - min: 0, + min: -1, max: 1, defaultValue: defaultParams.strokeTaper, - description: 'how much the stroke is loosing width away from center (0 = full visibility)', + description: + 'Stroke width taper along the spiral; positive = stroke fades out away from center, negative = stroke grows away from center (0 = uniform width)', }, { name: 'strokeCap', diff --git a/packages/shaders-react/src/shaders/spiral.tsx b/packages/shaders-react/src/shaders/spiral.tsx index 541c412c1..4f2dfa407 100644 --- a/packages/shaders-react/src/shaders/spiral.tsx +++ b/packages/shaders-react/src/shaders/spiral.tsx @@ -28,7 +28,7 @@ export const defaultPreset: SpiralPreset = { strokeTaper: 0, strokeCap: 0, noise: 0, - noiseFrequency: 0, + noiseFrequency: 0.3, softness: 0, speed: 1, frame: 0, diff --git a/packages/shaders/src/shaders/spiral.ts b/packages/shaders/src/shaders/spiral.ts index e212210da..d275fff13 100644 --- a/packages/shaders/src/shaders/spiral.ts +++ b/packages/shaders/src/shaders/spiral.ts @@ -29,8 +29,8 @@ import { simplexNoise, declarePI, colorBandingFix } from '../shader-utils.js'; * - u_density (float): Spacing falloff simulating perspective, 0 = flat spiral (0 to 1) * - u_distortion (float): Power of shape distortion applied along the spiral (0 to 1) * - u_strokeWidth (float): Thickness of spiral curve (0 to 1) - * - u_strokeTaper (float): How much stroke loses width away from center, 0 = full visibility (0 to 1) - * - u_strokeCap (float): Extra stroke width at the center, no effect with strokeWidth = 0.5 (0 to 1) + * - u_strokeTaper (float): Positive = stroke fades out away from center, negative = stroke grows away from center, 0 = uniform width + * - u_strokeCap (float): Extra stroke width added at the center, independent of strokeWidth (0 to 1) * - u_noise (float): Noise distortion applied over the canvas, no effect with noiseFrequency = 0 (0 to 1) * - u_noiseFrequency (float): Noise frequency, no effect with noise = 0 (0 to 1) * - u_softness (float): Color transition sharpness, 0 = hard edge, 1 = smooth gradient (0 to 1) @@ -43,6 +43,7 @@ precision mediump float; uniform float u_time; +uniform vec2 u_resolution; uniform vec4 u_colorBack; uniform vec4 u_colorFront; uniform float u_density; @@ -54,15 +55,17 @@ uniform float u_noise; uniform float u_noiseFrequency; uniform float u_softness; +in vec2 v_objectUV; in vec2 v_patternUV; out vec4 fragColor; -${ declarePI } -${ simplexNoise } +${declarePI} +${simplexNoise} void main() { vec2 uv = 2. * v_patternUV; + vec2 uvObj = 2. * v_objectUV; float t = u_time; float l = length(uv); @@ -76,35 +79,50 @@ void main() { float offset = l + angleNormalised; offset -= u_distortion * (sin(4. * l - .5 * t) * cos(PI + l + .5 * t)); float stripe = fract(offset); - + float shape = 2. * abs(stripe - .5); - float width = 1. - clamp(u_strokeWidth, .005 * u_strokeTaper, 1.); + float r = clamp(l, 0., 1.); + float wCap = 1. - r * r * (3. - 2. * r); + float cap = clamp(.5 * u_strokeCap * wCap, 0., 1.); + + float taperArea = length(uvObj);; + float tapper = pow(u_strokeTaper, 1. + 2. * (1. - u_strokeWidth)) * taperArea; + + float width = 1. - clamp(u_strokeWidth, 0., 1.); + width = mix(width, 1., tapper); + + width -= cap; + + float shapeSlope = 2. * sign(stripe - .5); + vec2 dOffset = vec2(dFdx(offset), dFdy(offset)); + vec2 dWidth = vec2(dFdx(width), dFdy(width)); + float fw = length(shapeSlope * dOffset - dWidth); - float wCap = mix(width, (1. - stripe) * (1. - step(.5, stripe)), (1. - clamp(l, 0., 1.))); - width = mix(width, wCap, u_strokeCap); - width *= (1. - clamp(u_strokeTaper, 0., 1.) * l); + float endProx = clamp(2. * abs(width - .5), 0., 1.); + fw *= 1. + pow(endProx, 6.); - float fw = fwidth(offset); - float fwMult = 4. - 3. * (smoothstep(.05, .4, 2. * u_strokeWidth) * smoothstep(.05, .4, 2. * (1. - u_strokeWidth))); - float pixelSize = mix(fwMult * fw, fwidth(shape), clamp(fw, 0., 1.)); - pixelSize = mix(pixelSize, .002, u_strokeCap * (1. - clamp(l, 0., 1.))); + shape = mix(shape, 0., tapper); + float res = smoothstep(width - fw - u_softness, width + fw + u_softness, shape); - float res = smoothstep(width - pixelSize - u_softness, width + pixelSize + u_softness, shape); + float dw = clamp(length(dWidth), .1, .9); + res *= 1. - smoothstep(1. - dw, 1. + dw, width); - vec3 fgColor = u_colorFront.rgb * u_colorFront.a; - float fgOpacity = u_colorFront.a; - vec3 bgColor = u_colorBack.rgb * u_colorBack.a; - float bgOpacity = u_colorBack.a; + vec3 fgColor = u_colorFront.rgb * u_colorFront.a; + float fgOpacity = u_colorFront.a; + vec3 bgColor = u_colorBack.rgb * u_colorBack.a; + float bgOpacity = u_colorBack.a; - vec3 color = fgColor * res; - float opacity = fgOpacity * res; + vec3 color = fgColor * res; + float opacity = fgOpacity * res; - color += bgColor * (1. - opacity); - opacity += bgOpacity * (1. - opacity); + color += bgColor * (1. - opacity); + opacity += bgOpacity * (1. - opacity); - ${ colorBandingFix } + ${colorBandingFix} +// color.r = shape; + fragColor = vec4(color, opacity); } `;