Android OpenGL ES實現簡單綠幕摳圖

正文

實現綠幕摳圖,其實想法很簡單。 這裡簡單粗暴的使用著色器替換。

OES Filter

直接實現在相機預覽上的Shader

#extension GL_OES_EGL_image_external : require
precision mediump float;
                                
varying vec2 vTextureCoordinate;
uniform samplerExternalOES uTexture;

const float pixel = 30.0;
void main() {
    vec4 tc = texture2D(uTexture, vTextureCoordinate);
    float r = tc.x * 255.0;
    float g = tc.y * 255.0;
    float b = tc.z * 255.0;

    if(g>140.0 && r<128.0 && b<128.0){
        tc.x =1.0;
        tc.y =1.0;
        tc.z =1.0;
         tc.w =0.0;
    }else{
     tc.w =1.0;
    }

    gl_FragColor = tc, 1.0;
}

這裡的關鍵是,判斷顏色的范圍。這裡簡單的認定 g>140.0 && r<128.0 && b<128.0 時為綠色。當是綠色的時候,就將其顏色換成白色。同時alpha值設置為0.0

BlendShader Filter

這個Shader是將背景的紋理,進行貼圖,貼到我們扣的這部分圖上。

precision mediump float;

varying vec2 vTextureCoord;
varying vec2 vExtraTextureCoord;

uniform sampler2D uTexture;
uniform sampler2D uExtraTexture;

void main() {
    vec4 base = texture2D(uTexture, vTextureCoord);
    vec4 overlay = texture2D(uExtraTexture, vExtraTextureCoord);
    vec4 outputColor;
    if(base.r==1.0 && base.g==1.0 && base.b==1.0 && base.a==0.0){
      outputColor.r = base.a*base.r + overlay.r * (1.0 - base.a);
      outputColor.g = base.a*base.g + overlay.g * (1.0 - base.a);
      outputColor.b = base.a*base.b + overlay.b * (1.0 - base.a);
      outputColor.a = base.a;
    }else{
       outputColor.r = base.r;
       outputColor.g = base.g;
       outputColor.b = base.b;
       outputColor.a = base.a;
    }
    gl_FragColor = outputColor;
}

這個shader就是加載瞭兩個貼圖。一個是來自上面相機的FBO的OffscreenTextureId,一個是來自我們另外的背景貼圖。 這段代碼就算,如果是辨認到之前我們處理的區域的話,就將兩個圖片貼加到一起,如果是范圍內,就用原來的圖片。

簡單的綠幕摳圖很簡單,隻是判斷到對應的顏色,然後將對應的貼圖貼到這個部分上,就可以瞭。

最後的效果

  • 屏幕中的原圖

最後的效果

缺陷

邊緣情況比較明顯。顯示比較突兀。 我們可以做的更好嗎?

更多關於Android OpenGL ES綠幕摳圖的資料請關註WalkonNet其它相關文章!

推薦閱讀: