Как можно смешать вывод 2 LUT на видео в GPUImage, не проходя последовательность? - PullRequest
0 голосов
/ 22 мая 2018

Я пытался выяснить, есть ли у GPUImage нестандартное решение для того, что я пытаюсь сделать.

У меня есть 2 LUT и видеофайл.На данный момент я могу успешно воспроизвести видеофайл и отфильтровать его по обоим LUT, используя комбинацию GPUImageView, GPUImageMovie, GPUImagePicture и GPUImageLookupFilter.

Это то, что я делаю в данный момент, чтобы добитьсяэто и работает хорошо:

    lutPicture1 = [[GPUImagePicture alloc] initWithImage:lutImage1];
    lutPicture2 = [[GPUImagePicture alloc] initWithImage:lutImage2];

    lutFilter1 = [[GPUImageLookupFilter alloc] init];
    lutFilter2 = [[GPUImageLookupFilter alloc] init];

    playerItem =  [[AVPlayerItem alloc] initWithURL:fileURL];
    player = [[AVPlayer alloc] initWithPlayerItem:playerItem];

    GPUImageMovie *gpuImageMovie = [[GPUImageMovie alloc] initWithPlayerItem:playerItem];

    [gpuImageMovie addTarget: lutFilter1];
    [lutPicture1 addTarget: lutFilter1];
    [lutPicture1 processImage];
    [lutFilter1 addTarget: lutFilter2];

    [lutPicture2 addTarget: lutFilter2];
    [lutPicture2 processImage];
    [lutFilter2 addTarget: gpuImageView];

    [gpuImageMovie startProcessing];
    [player play];

Поправьте меня, если я ошибаюсь, но результат будет результатом первой передачи его через мой фильтр с именем "lutFilter1", ТО перед передачей его через "lutFilter2"".

Однако я не хочу выполнять фильтры в такой последовательности.

Я не знаю, возможно ли это, но я хотел бы иметь возможность выполнитьследующее:

  1. учитывая "позицию" в моем видео
  2. получить соответствующий цвет для него из "lutImage1"
  3. получить соответствующий цвет для него от "lutImage2"
  4. смешивает цвета, возвращаемые из" lutImage1 "и" lutImage2 "
  5. , возвращает смешанный цвет в качестве вывода.

Я видел фильтр вфреймворк называется GPUImageSoftEleganceFilter, который выглядит так, как будто он может сделать что-то похожее, используя два LUT, но будучи относительно новым для этого материала, я хотел бы, чтобы кто-нибудь помог мне и сказал, достижимо ли то, что я пытаюсь сделать с помощью GPUImage, и если да, товозможно, направьте меня в правильном направлении:)

Спасибо!

1 Ответ

0 голосов
/ 23 мая 2018

Хорошо. Я понял, что класс для обработки того, что я пытаюсь сделать в GPUImage , GPUImageThreeInputFilter .

В итоге я создал подкласс GPUImageThreeInputFilter и добавление моих пользовательских вершинных и фрагментных шейдеров в мой подкласс.

Если вы хотите сделать то же самое, вот базовая настройка вершинных шейдеров, с которой можно начать:

attribute vec4 position;
attribute vec4 inputTextureCoordinate;
attribute vec4 inputTextureCoordinate2;
attribute vec4 inputTextureCoordinate3;

varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
varying vec2 textureCoordinate3;

void main()
{
    gl_Position = position;
    textureCoordinate = inputTextureCoordinate.xy;
    textureCoordinate2 = inputTextureCoordinate2.xy;
    textureCoordinate3 = inputTextureCoordinate3.xy;
}

И базовый фрагментный шейдер, чтобы согласиться с этим.ПРИМЕЧАНИЕ. Фрагментный шейдер, приведенный ниже, не использует текстуру изображения, визуализированную в местоположении 3, но было бы просто изменить это, если вы пожелаете.Также обратите внимание, что «интенсивность» должна быть установлена, вы можете жестко кодировать с плавающей точкой, например, 1.0 для демонстрационных целей.

varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
varying highp vec2 textureCoordinate3;

uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
uniform sampler2D inputImageTexture3;

uniform lowp float intensity;

void main()
{
    highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);

    highp float blueColor = textureColor.b * 63.0;

    highp vec2 quad1;
    quad1.y = floor(floor(blueColor) / 8.0);
    quad1.x = floor(blueColor) - (quad1.y * 8.0);

    highp vec2 quad2;
    quad2.y = floor(ceil(blueColor) / 8.0);
    quad2.x = ceil(blueColor) - (quad2.y * 8.0);

    highp vec2 texPos1;
    texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
    texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);

    highp vec2 texPos2;
    texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
    texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);

    lowp vec4 newColor1 = texture2D(inputImageTexture2, texPos1);
    lowp vec4 newColor2 = texture2D(inputImageTexture2, texPos2);

    lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));
    gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), intensity);
}

И моя установка Objective-C для подключения всего этого выглядит следующим образом:

// The URL of the video file in our Bundle we want to play
NSURL *videoFileURL = [NSURL fileURLWithPath: videoFilePath];

playerItem =  [[AVPlayerItem alloc] initWithURL: videoFileURL];
player = [[AVPlayer alloc] initWithPlayerItem: playerItem];

// GPUCustomThreeInputFilter inherits from GPUImageThreeInputFilter
customThreeInputFilter = [[GPUCustomThreeInputFilter alloc] init];

GPUImageMovie *gpuImageMovie = [[GPUImageMovie alloc] initWithPlayerItem:playerItem];
[gpuImageMovie addTarget: customThreeInputFilter atTextureLocation:0];

// This texture will be available at "inputImageTexture2" in our fragment shader
[gpuImagePicture1 addTarget: customThreeInputFilter atTextureLocation:1];
[gpuImagePicture1 processImage];

// This texture will be available at "inputImageTexture3" in our fragment shader
[gpuImagePicture2 addTarget: customThreeInputFilter atTextureLocation:2];
[gpuImagePicture2 processImage];

// gpuImageView is an instance of GPUImageView and is added to our ViewController in the normal way via [self.view addSubview: gpuImageView]
[customThreeInputFilter addTarget: gpuImageView];

[gpuImageMovie startProcessing];
[player play];

Надеюсь, это поможет любому, кто пытается сделать то же самое.

...