// luma.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors import type {ShaderPass} from '@luma.gl/shadertools'; import {warp} from './warp'; const source = /* wgsl */ `\ uniform swirlUniforms { radius: f32, angle: f32, center: vec2f, }; @group(0) @binding(1) swirl: swirlUniforms; fn swirl_warp(vec2 coord, vec2 texCenter) -> vec2f { coord -= texCenter; float distance = length(coord); if (distance < swirl.radius) { float percent = (swirl.radius - distance) / swirl.radius; float theta = percent * percent * swirl.angle; float s = sin(theta); float c = cos(theta); coord = vec2( coord.x * c - coord.y * s, coord.x * s + coord.y * c ); } coord += texCenter; return coord; } fn swirl_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) -> vec4f { vec2 coord = texCoord * texSize; coord = swirl_warp(coord, swirl.center * texSize); return warp_sampleColor(source, texSize, coord); } `; const fs = /* glsl */ `\ uniform swirlUniforms { float radius; float angle; vec2 center; } swirl; vec2 swirl_warp(vec2 coord, vec2 texCenter) { coord -= texCenter; float distance = length(coord); if (distance < swirl.radius) { float percent = (swirl.radius - distance) / swirl.radius; float theta = percent * percent * swirl.angle; float s = sin(theta); float c = cos(theta); coord = vec2( coord.x * c - coord.y * s, coord.x * s + coord.y * c ); } coord += texCenter; return coord; } vec4 swirl_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { vec2 coord = texCoord * texSize; coord = swirl_warp(coord, swirl.center * texSize); return warp_sampleColor(source, texSize, coord); } `; /** * Warps a circular region of the image in a swirl. */ export type SwirlProps = { /** [x, y] coordinates of the center of the circle of effect. default: [0.5, 0.5] */ center?: [number, number]; /** The radius of the circular region. */ radius?: number; /** The angle in radians that the pixels in the center of the circular region will be rotated by. */ angle?: number; }; export type SwirlUniforms = SwirlProps; /** * Warps a circular region of the image in a swirl. */ export const swirl = { name: 'swirl', dependencies: [warp], source, fs, props: {} as SwirlProps, uniforms: {} as SwirlProps, uniformTypes: { center: 'vec2', radius: 'f32', angle: 'f32' }, propTypes: { center: {value: [0.5, 0.5]}, radius: {value: 200, min: 1, softMax: 600}, angle: {value: 3, softMin: -25, softMax: 25} }, passes: [{sampler: true}] } as const satisfies ShaderPass;