0

I'm new to OpenGL. My goal is to work on an alpha video in a OpenGL structure in a textureview. I started with Video Effects and try to modify some colors (for start: black to transparent) using a custom [EDITED] shader:

#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES sTexture;
vec3 first;
vec4 second;
varying vec2 vTextureCoord;
vec2 oTextureCoord;
void main() {
   first[0] = 0.0;
   first[1] = 0.0;
   first[2] = 0.0;
   second[0] = 0.0;
   second[1] = 1.0;
   second[2] = 0.0;
   second[3] = 1.0;
   vec4 color = texture2D(sTexture, vTextureCoord);
   oTextureCoord = vec2(vTextureCoord.x ,vTextureCoord.y + 0.5);
   vec4 color2 = texture2D(sTexture, oTextureCoord);
   if(vTextureCoord.y < 0.5){
      gl_FragColor = vec4(color.r , color.g, color.b, color2.b);
   }else{
      gl_FragColor = color;

                                                                 }

But I never saw the background under the view. After some research I added

GLES20.glEnable(GLES20.GL_BLEND);

But now the "transparent color" is a green one :/

To add more information: the source video is a combination of colored frames on the upper part and the alpha mask on the bottom one.

Am I doing it wrong?

thanks by advance.

[EDIT] Here is my actual onDrawFame method:

@Override
    public void onDrawFrame(GL10 glUnused) {
        synchronized (this) {
            if (updateSurface) {
                mSurface.updateTexImage();
                mSurface.getTransformMatrix(mSTMatrix);
                updateSurface = false;
            }
        }
        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

        GLES20.glClearColor(1.0f,1.0f, 1.0f, 0.0f);
        GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT
                | GLES20.GL_COLOR_BUFFER_BIT);


        GLES20.glUseProgram(mProgram);
        checkGlError("glUseProgram");

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID[0]);

        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
        GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT,
                false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,
                mTriangleVertices);
        checkGlError("glVertexAttribPointer maPosition");
        GLES20.glEnableVertexAttribArray(maPositionHandle);
        checkGlError("glEnableVertexAttribArray maPositionHandle");

        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
        GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT,
                false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,
                mTriangleVertices);
        checkGlError("glVertexAttribPointer maTextureHandle");
        GLES20.glEnableVertexAttribArray(maTextureHandle);
        checkGlError("glEnableVertexAttribArray maTextureHandle");

        Matrix.setIdentityM(mMVPMatrix, 0);
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix,
                0);
        GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);

        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
        checkGlError("glDrawArrays");
        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
        GLES20.glFinish();

    }

--[EDIT]-- Here is my vertexShader :

uniform mat4 uMVPMatrix;
uniform mat4 uSTMatrix;
attribute vec4 aPosition;
attribute vec4 aTextureCoord;
varying vec2 vTextureCoord
void main() { 
  gl_Position = uMVPMatrix * aPosition;
  vTextureCoord = (uSTMatrix * aTextureCoord).xy;
}
Thibaud Renaux
  • 280
  • 1
  • 17

2 Answers2

2

To improve my question here is some details. Here is my source: source

And here is my goal (alpha chanel): goal

when I let clear color with :

GLES20.glClearColor(1f, 1f, 0.9f, 0f);

There is also the yellow background as you can see ! How can I got a transparent view to see the blue one on this picture? enter image description here

[ANSWER : HOW TO RESOLVE]

1.First, You need to set your GLSurfaceView to allow Transparency in your constructor as:

this.getHolder().setFormat(PixelFormat.RGB_565);
this.getHolder().setFormat(PixelFormat.TRANSPARENT);
setEGLConfigChooser(8,8,8,8,16,0);
setEGLContextClientVersion(2);// all this before setRenderer()

2.Ask for transparency in your onDrawFrame method :

GLES20.glClearColor(0.0f, 0.0f, 0.0f, .0f);// 
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT|GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

For me only black transparent color worked rgba(0,0,0,0).

Thanks again for contributors who helped me.

--[EDIT : REMAINING PROBLEM]--

Here some exemple :

enter image description here

On top it's an GLSurfaceView with an alpha video and down a custom GLTextureView, both are in an horizontalView. Top appears to be good as I want! But check this when I scroll to right: enter image description here

Top still appear when bottom hide as it needed!

Thibaud Renaux
  • 280
  • 1
  • 17
  • Shouldn't you clear to (.0f, .0f, .0f, .0f)? In your blending case the alpha will not be set to 0. Or maybe just disable the blend in the case you have now. – Matic Oblak Jan 05 '16 at 14:49
  • I Just tried `GLES20.glClearColor(.0f, .0f, .0f, .0f);` and under these three lines : `GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT| GLES20.GL_COLOR_BUFFER_BIT);` `GLES20.glEnable(GLES20.GL_BLEND);` and `GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);` and not working (black background) – Thibaud Renaux Jan 05 '16 at 16:51
  • So I assume the black background is the whole GL surface view and the blue one is some other view. If so what you are seeing is correct but you need a way to enable a transparent GL surface view so it mixes with other views in your pipeline. Try searching around the web a bit for it. Maybe there is just a property such as opaque that needs to be disabled... – Matic Oblak Jan 05 '16 at 16:54
  • http://stackoverflow.com/questions/5391089/how-to-make-surfaceview-transparent seems promising.. – Matic Oblak Jan 05 '16 at 16:57
  • Thanks @MaticOblak , I will Post a Resume of what I did with all your advices to resolve this Problem – Thibaud Renaux Jan 06 '16 at 09:14
  • If making your surface view support transparency fixed the issue and produced the desired results I should edit my answer and put rest of the details in there. Is that the case? – Matic Oblak Jan 06 '16 at 09:19
  • Two things makes it works : rgba(0,0,0,0) and a mix of your link and this one http://stackoverflow.com/questions/17878645/glsurfaceview-how-to-make-translucent-background – Thibaud Renaux Jan 06 '16 at 09:29
  • I can't see your changes , where have you added it? – Thibaud Renaux Jan 06 '16 at 10:23
  • The changes are in my answer. – Matic Oblak Jan 06 '16 at 10:24
  • Hi again @MaticOblak , I swapped my GLSurfaceView to a GLTexture view from https://gist.github.com/eleventigers/9545428 , but a hole appeared, do you know or guess where is the problem? – Thibaud Renaux Jan 08 '16 at 13:46
  • Well the holes are quite tricky. It might be anything from a gun shot, a small meteorite, a strange blend function or even a collapsing star. Maybe if you described the hole a bit we might be able to try and identify the issue a bit more in depth. – Matic Oblak Jan 08 '16 at 14:04
  • Well, this hole is the background of my GLTextureView but I see the alpha video I wanted. The GLTextureView punch a hole to it's parent background image . I swapped from Surface to Texture view because of to show the video it has to be with setZOrderOnTop but no more attachement to parent and without it's a hole. With textureview It's attached and visible but in this hole :/ – Thibaud Renaux Jan 08 '16 at 14:49
  • Could you please create a new question with screenshot attached and showing what view is what and what is the expected result. It seems this is a bit too much to explain here or I just fail to understand it. – Matic Oblak Jan 08 '16 at 14:53
  • @MaticOblak here the new post : http://stackoverflow.com/questions/34636378/gltextureview-create-hole-behind-it – Thibaud Renaux Jan 11 '16 at 09:33
0

Just a quick look through your code seems to already have quite a few strange peaces. I wish you included your vertex data (the position and texture coordinates) at least. First please check the line

GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT,
                false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,
                mTriangleVertices);

These look like texture coordinates and you are having 3 dimensions? Is that correct? Fortunately if the stride is correct the dimensions will make no effect but still.

So if I understand that the top part of the video frame represents the color and the bottom does the alpha then your shader makes little sense to me. Could you show the vertex shader as well? Anyway what I would expect you to do is use the texture coordinates in range [0, 1], representing the whole texture. Then in the vertex shader have 2 varying vec2 texture coordinates such that:

varying vec2 colorTextureCoordinates = vec2(textureCoordinates.x, textureCoordinates.y*.5); // representing the top part
varying vec2 alphaTextureCoordinates = vec2(textureCoordinates.x, textureCoordinates.y*.5 + .5); // representing the bottom part

Then in the fragment shader all you do is mix the 2:

vec3 color = texture2D(sTexture, colorTextureCoordinates).rgb;
float alpha = texture2D(sTexture, alphaTextureCoordinates).b; // Why .b?
gl_FragColor = vec4(color, alpha);

Or am I missing something? Why is there an IF statement in your fragment shader that suggest that the top of the texture would use the color and the bottom part would use the color plus the alpha (or the other way around).

I suggest you first try to draw the image you receive from the video with the most common texture shader to confirm the whole frame is being drawn correctly. Then you should check the alpha is working correctly by feeding the semitransparent shader gl_FragColor = vec4(color.rgb, .5). After you confirm both of these produce expected results you should try drawing only the top part of the frame (the color) by using colorTextureCoordinates to get the expected results (the transparent parts should be black). Then check the alpha part by using alphaTextureCoordinates and gl_FragColor = vec4(alpha, alpha, alpha, 1.0) which should produce a grayscale image where white is a full alpha and black is no alpha. After all of these are confirmed try putting it all together as written above.

To make the surface view blend with other views you need to set the transparency and you need to fill the transparent pixels with the transparent color.

Since you are using blend you will need to clear the background to clear color (.0f, .0f, .0f, .0f). Simply disabling the blend should produce the same result in your case.

After doing so you will still see a black background because the surface view will not implicitly blend with other views (the background) and only RGB part is used to fill the rendered view. To enable the transparency you should take a look at some other answers and also this one.

Community
  • 1
  • 1
Matic Oblak
  • 16,318
  • 3
  • 24
  • 43
  • Thanks,Why `.b`? , because the mask is a gray level mask, so blue, red and green have same value and to be sure calculation would be like alpha = (.r +.g + .b) / 3 But as you can see if three have same value is unecessary to do it ! Why an IF ? I don’t really need it in fact! the goal is to have, at the end, just the upper part and the ANDROID view should be half height to hide the useless! – Thibaud Renaux Jan 05 '16 at 13:22
  • I thought so but usually developer use ".x" or ".r" as the first component. Since you used the third component It might have some significant meaning so it is best to just ask. Let us know if you find any difficulties or find some unexpected results after trying to apply these procedures so we may further advise. – Matic Oblak Jan 05 '16 at 13:27
  • I found the problem of my implementation of your answers : I forgot to modify also the color Y coordinates as : `colorTextureCoordinates = vec2(vTextureCoord.x, vTextureCoord.y*.5);`. The alpha problem still remain sadly – Thibaud Renaux Jan 05 '16 at 14:43