I\'m quite new to OpenGL
/Metal
and I\'m trying to understand some fundamental concepts.
Within our app, we are using CIFilter
to filte
I gave it a try. Here's the kernel code:
#include <metal_stdlib>
using namespace metal;
#include <CoreImage/CoreImage.h>
extern "C" { namespace coreimage {
float4 vhs(sampler_h src, float time, float amount) {
const float magnitude = sin(time) * 0.1 * amount;
float2 greenCoord = src.coord(); // this is alreay in relative coords; no need to devide by image size
const float split = 1.0 - fract(time / 2.0);
const float scanOffset = 0.01;
float2 redCoord = float2(greenCoord.x + magnitude, greenCoord.y);
float2 blueCoord = float2(greenCoord.x, greenCoord.y + magnitude);
if (greenCoord.y > split) {
greenCoord.x += scanOffset;
redCoord.x += scanOffset;
blueCoord.x += scanOffset;
}
float r = src.sample(redCoord).r;
float g = src.sample(greenCoord).g;
float b = src.sample(blueCoord).b;
return float4(r, g, b, 1.0);
}
}}
And here some slight adjustments to outputImage
in your filter:
override var outputImage: CIImage? {
guard let inputImage = self.inputImage else { return nil }
// could be filter parameters
let inputTime: NSNumber = 60
let inputAmount: NSNumber = 0.3
// You need to tell the kernel the region of interest of the input image,
// i.e. what region of input pixels you need to read for a given output region.
// Since you sample pixels to the right and below the center pixel, you need
// to extend the ROI accordingly.
let magnitude = CGFloat(sin(inputTime.floatValue) * 0.1 * inputAmount.floatValue)
let inputExtent = inputImage.extent
let roiCallback: CIKernelROICallback = { _, rect -> CGRect in
return CGRect(x: rect.minX, y: rect.minY,
width: rect.width + (magnitude + 0.01) * inputExtent.width, // scanOffset
height: rect.height + magnitude * inputExtent.height)
}
return self.kernel.apply(extent: inputExtent,
roiCallback: roiCallback,
arguments: [inputImage, inputTime, inputAmount])
}