将OpenGL着色器转换为Metal(Swift)以在CIFilter中使用

时间:2019-07-20 01:29:49

标签: swift opengl shader metal cifilter

我对OpenGL / Metal还是陌生的,我正在尝试了解一些基本概念。
在我们的应用程序中,我们使用CIFilter过滤视频。我看过2017年的WWDC视频,解释了您可以将CIFilterMetal包装起来,并将其用作常规过滤器。
我正在尝试了解如何将此OpenGL视频效果转换为Metal,以便可以将其用作将来效果的参考点。

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
float amount = sin(iTime) * 0.1;

// uv coords
vec2 uv = fragCoord / iResolution.xy;

amount *= 0.3;
float split = 1. - fract(iTime / 2.);
float scanOffset = 0.01;
vec2 uv1 = vec2(uv.x + amount, uv.y);
vec2 uv2 = vec2(uv.x, uv.y + amount);
if (uv.y > split) {
    uv.x += scanOffset;
    uv1.x += scanOffset;
    uv2.x += scanOffset;
}


float r = texture(iChannel0, uv1).r;
float g = texture(iChannel0, uv).g;
float b = texture(iChannel0, uv2).b;

fragColor = vec4(r, g, b, 1.);

}

哪个产生:

enter image description here

OpenGL代码转换为Metal后,我使用CIFilter包装器将其与AVPlayerItem一起使用:

class MetalFilter: CIFilter {

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

private let kernel: CIKernel
var inputImage: CIImage?

override init() {
    let url = Bundle.main.url(forResource: "default", withExtension: "metallib")!
    let data = try! Data(contentsOf: url)
    kernel = try! CIKernel(functionName: "vhs", fromMetalLibraryData: data)
    super.init()
}


func outputImage() -> CIImage? {
    guard let inputImage = inputImage else {return nil}
    let sourceSize = inputImage.extent.size
    let outputImage = kernel.apply(extent: CGRect(x: 0, y: 0, width: sourceSize.width, height: sourceSize.height), roiCallback: { index, destRect in
        return destRect
    }, arguments: [inputImage, NSNumber(value: Float(1.0 / sourceSize.width)), NSNumber(value: Float(1.0 / sourceSize.height)), NSNumber(value: 60.0)])

    return outputImage
   }
}

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:3)

我尝试了一下。这是内核代码:

var dro = 5;
var saboloo = 0;
function setup(){
    var es = $('#dro');
    dro--;
    es.html(dro);
    if(dro == 0){
        es.html(clearInterval(setupInterval)); // clear the interval using the correct reference
    }
}
var setupInterval = setInterval(setup, 1000); // setupInterval is the reference

以下是对过滤器中的#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); } }} 的一些细微调整:

outputImage