Как замаскировать шейдер фрагментов

#android #opengl-es #camera #fragment-shader

Вопрос:

Я хочу реализовать размытие заднего плана для селфи-камеры.
У меня есть шейдер фрагментов размытия

 precision mediump float;

uniform sampler2D uSampler;
uniform float uBlur;
uniform float uRadius;

varying vec2 vTextureCoord;

void main() {
  vec3 sum = vec3(0);
  if (uBlur > 0.0) {
    for (float i = -uBlur; i < uBlur; i  ) {
      for (float j = -uBlur; j < uBlur; j  ) {
        sum  = texture2D(uSampler, vTextureCoord   vec2(i, j) * (uRadius / uBlur)).rgb / pow(uBlur * 2.0, 2.0);
      }
    }
  } else {
    sum = texture2D(uSampler, vTextureCoord).rgb;
  }
  gl_FragColor = vec4(sum, 1.0);
}
 

Также у меня есть массив, который указывает, где мне нужно поместить эффект размытия.
Моя идея состоит в том, чтобы каким-то образом передать массив шейдеру фрагментов и пропустить координаты, которые не должны быть размыты.
Есть ли какой-нибудь способ сделать это или есть какой-то другой способ, которому я должен следовать?

UPD0: Маска генерируется динамически несколько раз в секунду. Данные маски, содержащиеся в com.google.mlkit.vision.segmentation.SegmentationMask классе, — у него есть ByteBuffer с width и heigh внутри. Я попытался создать растровое изображение с Bitmap.createBitmap(maskColorsFromByteBuffer(mask), maskWidth, maskHeight, Config.ARGB_8888) помощью и

     private int[] maskColorsFromByteBuffer(ByteBuffer byteBuffer) {
        @ColorInt int[] colors = new int[maskWidth * maskHeight];
        for (int i = 0; i < maskWidth * maskHeight; i  ) {
            float backgroundLikelihood = 1 - byteBuffer.getFloat();
            if (backgroundLikelihood > 0.9) {
                colors[i] = Color.argb(128, 51, 112, 69);
            } else if (backgroundLikelihood > 0.2) {
                // Linear interpolation to make sure when backgroundLikelihood is 0.2, the alpha is 0 and
                // when backgroundLikelihood is 0.9, the alpha is 128.
                //  0.5 to round the float value to the nearest int.
                int alpha = (int) (182.9 * backgroundLikelihood - 36.6   0.5);
                colors[i] = Color.argb(alpha, 51, 112, 69);
            }
        }
        return colors;
    }
 

После создания растрового изображения я попытался нарисовать его с помощью ImageObjectFilterRender — насколько я вижу, этот класс генерирует текстуру из растрового изображения.

Комментарии:

1. Почему бы не сохранить маску в текстуре?

2. Как это должно работать? Маска-это динамическая вещь, которая меняется примерно 4 раза в течение секунды. Я попытался построить из него растровое изображение и использовать ImageObjectFilterRender класс отсюда github.com/pedroSG94/rtmp-rtsp-stream-client-java , но он слишком сильно отстает

3. «Маска-это динамичная вещь, которая меняется примерно 4 раза» — это новая информация. Однако это ничего не меняет. Обычный способ сделать это-с помощью текстуры, UB или SSBO. Как вы генерируете данные маски? Можете ли вы отобразить его в текстуру.

4. Пожалуйста, смотрите обновление 0 в описании.

5. Я понимаю. Поэтому загрузите данные маски ( color ) в текстуру. Создайте текстуру с glTexImage2D помощью (один раз) и обновите данные изображения с glTexSubImage2D помощью (после изменения маски).