DepthBlur

The DepthBlur kernel applies a box blur of varying size to an input. The size of the blur is controlled by a depth channel read from a second input.

The user can change the Focal Point: the depth at which zero blur will be applied. The maximum Size of the blur can also be user-controlled.

// Copyright (c) 2024 The Foundry Visionmongers Ltd.  All Rights Reserved.

// DepthBlur kernel: Applies a box blur to the first input, with the blur size at each pixel
// being determined by a "depth" value taken from the second input.
kernel DepthBlur : ImageComputationKernel<ePixelWise>
{
  Image<eRead, eAccessRanged2D, eEdgeClamped> src;
  Image<eRead, eAccessRandom> depth;
  Image<eWrite> dst;

param:
  float2 focus;
  int size;

  // In define(), parameters can be given labels and default values.
  void define() {
    defineParam(size, "Size", 10, eParamProxyScale);
    defineParam(focus, "Focal Point", float2(100.0f, 100.0f), eParamProxyScale);
  }

  // The init() function is run once before any calls to process().
  void init() {
    src.setRange(-size, size);
  }

  // The process function is run at every pixel to produce the output.
  void process(int2 pos) {
    // Get the depth at the current pixel
    const float depthHere = depth(pos.x, pos.y, 0);
    // Get the depth at the focal point
    const float depthAtFocus = bilinear(depth, focus[0], focus[1], 0);

    // Find the difference in depth between the current pixel and the focal point
    float z = fabs(depthHere - depthAtFocus);
                                   
    // Use the depth difference to set the blur size for the current pixel.
    const int blurSize = clamp((int)(z * size + 0.5f), 0, size);

    // Accumulate src values in a window of blurSize x blurSize.
    SampleType(src) sum = 0.0f;
    for (int j = -blurSize; j <= blurSize; j++) {
      for (int i = -blurSize; i <= blurSize; i++) {
        sum += src(i, j);
      }
    }
    
    // Normalise the blurred value and set it into the dst image.
    const int blurDiameter = 2 * blurSize + 1;
    dst() = sum / (blurDiameter * blurDiameter);
  }
};