Search code examples
cmetalcore-imagecifiltermetalkit

Convert Core Image Kernel Language function to Metal Shading Language


I have the following function in Core Image Kernel Language and I need something equivalent in Metal Shading Language, but I have problem with destCoord , unpremultiply and premultiply functions.

kernel vec4 MyFunc(sampler src, __color color, float distance, float slope) {
  vec4 t;
  float d;

  d = destCoord().y * slope + distance;
  t = unpremultiply(sample(src, samplerCoord(src)));
  t = (t - d*color) / (1.0-d);

  return premultiply(t);
}

My function in MSL so far is:

float4 MyFunc(sample_t image, float3 color, float dist, float slope) {
    float4 t;
    float d;
    
    d = color[1] * slope + dist
    ...
        
    return t;
}

Any help would be appreciated!


Solution

  • This should work:

    float4 MyFunc(sampler src, float4 color, float dist, float slope, destination dest) {
         const float d = dest.coord().y * slope + dist;
         float4 t = unpremultiply(src.sample(src.coord()));
         t = (t - d * color) / (1.0 - d);
    
         return premultiply(t);
    }
    

    Note the destination parameter. This is an optional last parameter to a kernel, that gives you access to information about the render destination (like the coordinate in destination-space that you are rendering to). You don't need to pass anything for this when invoking the CIKernel, Core Image will fill it automatically.

    Since you are only sampling the input src at the current location, you can also optimize the kernel to be a CIColorKernel. These are kernels that have a 1:1 mapping of input to output pixels. They can be concatenated by the Core Image runtime. The kernel code would look like this:

    float4 MyFunc(sample_t src, float4 color, float dist, float slope, destination dest) {
        const float d = dest.coord().y * slope + dist;
        float4 t = unpremultiply(src);
        t = (t - d * color) / (1.0 - d);
    
        return premultiply(t);
    }
    

    Notice sample_t (which is basically a float4) vs. sampler.