kuwahara

@three-blocks/coreWebGPUWebGL
kuwahara(originalTextureNode : Node, tensorTextureNode : Node, options : Object) : Node<vec4>

Generalized anisotropic Kuwahara painterly filter with multi-sector sampling.

Algorithm

  • Evaluates angular sectors around each pixel
  • Structure tensor drives dominant orientation, coherence, and anisotropic scaling
  • Selects sector with minimum variance for painterly effect
  • More sectors/angle steps = smoother results but slower performance
  • Using the structure tensor aligns the brush with image edges (high coherence) and reduces smearing across strong gradients; disabling it falls back to isotropic blurring.

Performance Tuning

  • Increase stepSize for sparse sampling (large radius with similar sample count)
  • Reduce sectors or angleSteps for speed
  • Enable useSimpleWeight for flatter look with fewer math ops

Debug Output

  • R: Selected sector id (0..1)
  • G: Edge coherence from structure tensor
  • B: Normalized variance (higher = noisier)
Parameters
originalTextureNodeNode
Source texture to filter.
tensorTextureNodeNode
Structure tensor texture (from structureTensor()).
optionsoptionalObject
Optional parameters.
Default is {}.
  • radiusoptionalnumber
    Filter radius in pixels (brush size).
    Default is 6.
  • sectorsoptionalnumber
    Number of angular sectors (more = smoother, slower).
    Default is 8.
  • angleStepsoptionalnumber
    Discrete angle steps per sector (angular smoothness).
    Default is 3.
  • useSimpleWeightoptionalboolean
    Use flat weighting instead of smooth polynomial falloff.
    Default is false.
  • stepSizeoptionalnumber
    Sparse sampling step (1=dense, >1=sparser/faster).
    Default is 1.
  • useTensoroptionalboolean
    Use structure tensor for orientation; when false, falls back to isotropic filtering.
    Default is true.
  • debugoptionalboolean
    Debug output (R=selected sector, G=edge coherence, B=variance).
    Default is false.
Returns
Node<vec4> — Filtered painterly color.
See also
Example
import { kuwahara, structureTensor } from '@three-blocks/core';
import { pass } from 'three/tsl';

const scenePass = pass(scene, camera);
const tensorPass = structureTensor(scenePass);

const painterly = kuwahara(scenePass, tensorPass, {
  radius: 6,
  sectors: 8,
  angleSteps: 3,
  stepSize: 1
});