I want to apply an alpha mask to a video. Each frame of the video has color information on top and alpha information at the bottom. Like this:
In my case, i want the white pixels in the alpha image to be transparent in the main image. I have an other texture that fills in those transparent pixels.
I was able to generate the only color images or only alpha images, but not able to apply the alpha on to the image. I am using GLES20 in android.
Here is my code which is giving a black screen:
private val vidVertexShaderCode =
"""
precision highp float;
attribute vec3 vertexPosition;
attribute vec4 uvs;
varying vec2 varUvs;
varying vec2 varMaskUvs;
uniform mat4 texMatrix;
uniform mat4 mvp;
void main()
{
varUvs = (texMatrix * vec4(uvs.x, uvs.y, 0, 1.0)).xy;
varMaskUvs = (texMatrix * vec4(uvs.x, uvs.y * 0.5, 0.1, 1.0)).xy;
gl_Position = mvp * vec4(vertexPosition, 1.0);
}
"""
private val vidFragmentShaderCode =
"""
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 varUvs;
varying vec2 varMaskUvs;
uniform samplerExternalOES texSampler;
void main()
{
vec2 m_uv = vec2(varMaskUvs.x, varMaskUvs.y);
vec4 mask = texture2D(texSampler, m_uv);
vec2 c_uv = vec2(varUvs.x, varUvs.y * 0.5);
vec4 color = texture2D(texSampler, c_uv);
gl_FragColor = vec4(color.rgb, color.a * mask.r)
}
"""
What am i doing wrong?
P.S. I am new to opengl.
Compute the v coordinate of the image (uvs.y * 0.5 + 0.5) and the mask (uvs.y * 0.5) in the vertex shader:
precision highp float;
attribute vec3 vertexPosition;
attribute vec4 uvs;
varying vec2 varUvs;
varying vec2 varMaskUvs;
uniform mat4 texMatrix;
uniform mat4 mvp;
void main()
{
varUvs = (texMatrix * vec4(uvs.x, uvs.y * 0.5 + 0.5, 0, 1.0)).xy;
varMaskUvs = (texMatrix * vec4(uvs.x, uvs.y * 0.5, 0.0, 1.0)).xy;
gl_Position = mvp * vec4(vertexPosition, 1.0);
}
You don't need any further transformation in the fragment shader:
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 varUvs;
varying vec2 varMaskUvs;
uniform samplerExternalOES texSampler;
void main()
{
vec4 mask = texture2D(texSampler, varMaskUvs);
vec4 color = texture2D(texSampler, varUvs);
gl_FragColor = vec4(color.rgb, color.a * mask.r)
}
Related
in opengl es program i input two textures and use fragment shader:
varying highp vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
uniform lowp float intensity;
void main() {
highp vec4 newColor = texture2D(inputImageTexture2,textureCoordinate2);
highp vec4 vColor = texture2D(inputImageTexture, textureCoordinate);
newColor.r = newColor.r + vColor.r * (1.0 - newColor.a);
newColor.g = newColor.g + vColor.g * (1.0 - newColor.a);
newColor.b = newColor.b + vColor.b * (1.0 - newColor.a);
gl_FragColor = vec4(mix(vColor.rgb, newColor.rgb, 0.86), newColor.a);
};
but the result have some "error color" here, how to fix this?
I found the answer myself, this is because I write and read from a same FBO texture, and now I change it and work fine!
I would like to draw a simple square and change the color dynamically so that it is the brightest in the center and darkest in the borders.
however when I am rendering I can't see anything .
here is my vertex shader:
uniform mat4 u_Matrix;
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
varying vec4 pos;
void main()
{
v_Color = a_Color;
pos = u_Matrix * a_Position;
gl_Position = pos;
}
and here is my fragment shader :
precision mediump float;
varying vec4 v_Color;
varying vec4 pos;
void main()
{
float len = length(normalize(pos));
gl_FragColor = vec4(1-len , 1-len , 1-len , 1);
}
You can't reference gl_Position in the fragment shader.
Either hand gl_Position over to the fragment shader
attribute vec4 a_Position;
varying vec4 pos;
void main()
{
pos = a_Position;
gl_Position = a_Position;
}
or use gl_FragCoord in the fragment shader float dist = length( gl_FragCoord - viewPortCenter ); if you want to work in window coordinates.
Also rather use length, which is faster, instead of doing your own distance calculation.
My shader works GREAT on iOS and Win32. The problem is Android. All devices really botch the normals if I send them as GL_BYTE. If I convert them to GL_FLOAT, everything's peachy.
glVertexAttribPointer(program->slots[Shaders::A_NORMAL_SLOT], 3, GL_FLOAT, GL_FALSE, 0, frame->normals);
glVertexAttribPointer(program->slots[Shaders::A_NORMAL_SLOT], 3, GL_BYTE, GL_TRUE, 0, frame->normals);
and YES, 'frame->normals' is of type float* in the first example, and of type char* in the second example. Like I said, this exact same code works great on iOS/Win32.
What's going on here? Is this some kind of Android bug that it won't accept byte normals?
My shader, Vertex:
uniform mat3 normal_matrix;
uniform mat4 mvp_matrix;
uniform vec3 u_lightpos;
uniform vec3 u_eyepos;
uniform vec4 u_color;
attribute vec4 a_vertex;
attribute vec3 a_normal;
attribute vec2 a_texcoord0;
attribute vec4 a_color;
varying vec2 v_texcoord0;
varying vec3 v_viewDir;
varying vec3 v_lightDir;
varying vec3 v_normal;
varying vec4 v_color;
void main( void )
{
vec4 fvObjectPosition = mvp_matrix * (a_vertex);
v_viewDir = u_eyepos;
v_lightDir = u_lightpos;
v_normal = normalize(normal_matrix * a_normal);
v_color = u_color * a_color;
v_texcoord0 = a_texcoord0.xy;
gl_Position = fvObjectPosition;
}
Fragment:
#ifdef GL_ES
precision mediump float;
#endif
uniform vec4 u_specular;
uniform vec4 u_diffuse;
uniform float u_specularpower;
uniform sampler2D t_texture0;
varying vec2 v_texcoord0;
varying vec3 v_viewDir;
varying vec3 v_lightDir;
varying vec3 v_normal;
varying vec4 v_color;
void main( void )
{
float fNDotL = dot( v_normal, v_lightDir );
vec3 fvReflection = normalize( ( ( 2.0 * v_normal ) * fNDotL ) - v_lightDir );
vec4 fvBaseColor = v_color * texture2D( t_texture0, v_texcoord0 );
vec4 fvTotalDiffuse = vec4((u_diffuse * fNDotL).xyz, 1.0) * fvBaseColor;
vec4 fvTotalSpecular = u_specular * ( pow( max( 0.0, dot( fvReflection, -v_viewDir ) ), u_specularpower ) );
gl_FragColor = vec4(( fvBaseColor + fvTotalDiffuse + fvTotalSpecular ).xyz, v_color.w);
}
I have a fragment shader :
precision mediump float;
uniform vec4 vColor;
uniform sampler2D u_Texture; // The input texture.
varying vec2 v_TexCoordinate; // Interpolated texture coordinate per fragment.
varying vec4 vAlpha;
void main() {
gl_FragColor = vec4(texture2D(u_Texture, v_TexCoordinate).xyz, texture2D(u_Texture, v_TexCoordinate).w * vAlpha[3]);
}
And vertex shader :
attribute vec3 vPosition;
attribute vec2 aTextureCoord; // Per-vertex texture coordinate information we will pass in.
attribute vec4 aAlpha;
varying vec2 v_TexCoordinate;
varying vec4 vAlpha;
void main() {
v_TexCoordinate = aTextureCoord;
vAlpha = aAlpha;
gl_Position = uMVPMatrix * vec4(vPosition,1.0);
}
And try to set alpha value to texture from my program.
private final int mAlphaHandle;
private float[] color = {0.5f};
Set :
mAlphaHandle = GLES20.glGetAttribLocation(mProgram,"aAlpha");
Using :
GLES20.glEnableVertexAttribArray(mAlphaHandle);
GLES20.glVertexAttribPointer(mAlphaHandle, 1,GLES20.GL_FLOAT, false,4, alphaBuffer);
Blending is enabled.
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
But i have no effect on the screen. So a question is why i getting no effect on the screen? Actually a want to change alpha value dynamically in the future.
I've been stuck for several days now, trying to make my shader working properly.
The problem is that when I'm not attaching a texture on my object, I multiply the ambient by the light color and I get a dark object when no light, and illuminated properly when a light source is activated.
The problem is that when I attach a texture and multiply it by ambient and light color I get a transparent object that shows up only when a light source is activated, and you can even see through the object while it is illuminated!
I've been trying several codes snippets from the internet but I always get the same result. What I'm doing wrong here? I'm desperate...
The application is developed on Android.
Here is my Vertex Shader:
uniform mat4 uMVPMatrix;
uniform mat4 normalMatrix;
// eye pos
uniform vec3 eyePos;
// position and normal of the vertices
attribute vec4 aPosition;
attribute vec3 aNormal;
// texture variables
uniform float hasTexture;
varying float tex;
attribute vec2 textureCoord;
varying vec2 tCoord;
// lighting
uniform vec4 lightPos;
uniform vec4 lightColor;
// material
uniform vec4 matAmbient;
uniform vec4 matDiffuse;
uniform vec4 matSpecular;
uniform float matShininess;
// normals to pass on
varying vec3 vNormal;
varying vec3 EyespaceNormal;
varying vec3 lightDir, eyeVec;
void main() {
// pass on texture variables
tex = hasTexture;
tCoord = textureCoord;
// normal
EyespaceNormal = vec3(normalMatrix * vec4(aNormal, 1.0));
// the vertex position
vec4 position = uMVPMatrix * aPosition;
// light dir
lightDir = lightPos.xyz - position.xyz;
eyeVec = -position.xyz;
gl_Position = uMVPMatrix * aPosition;
}
And here is my Fragment shader:
precision mediump float;
// texture variables
uniform sampler2D texture1; // color texture
varying float tex;
varying vec2 tCoord;
varying vec3 vNormal;
varying vec3 EyespaceNormal;
// light
uniform vec4 lightPos;
uniform vec4 lightColor;
// material
uniform vec4 matAmbient;
uniform vec4 matDiffuse;
uniform vec4 matSpecular;
uniform float matShininess;
// eye pos
uniform vec3 eyePos;
// from vertex s
varying vec3 lightDir, eyeVec;
void main() {
vec4 b = lightColor;
vec4 c = matAmbient;
vec4 d = matDiffuse;
vec4 e = matSpecular;
vec3 g = eyePos;
float f = matShininess;
vec3 N = normalize(EyespaceNormal);
vec3 E = normalize(eyeVec);
vec3 L = normalize(lightDir);
// Reflect the vector. Use this or reflect(incidentV, N);
vec3 reflectV = reflect(-L, N);
// Get lighting terms
vec4 ambientTerm;
if (tex >= 1.0) {
ambientTerm = texture2D(texture1, tCoord);
}
else
ambientTerm = matAmbient * lightColor;
vec4 diffuseTerm = matDiffuse * max(dot(N, L), 0.0);
vec4 specularTerm = matSpecular * pow(max(dot(reflectV, E), 0.0), matShininess);
gl_FragColor = ambientTerm * diffuseTerm + specularTerm;
}
Thanks in advance.
OK I found it, thanks to JPD002, I was revising the shader again, and I found out that it has to be
vec4 diffuseTerm = matDiffuse * max(dot(N, L), 0.0);
vec4 specularTerm = matSpecular * pow(max(dot(reflectV, E), 1.0), matShininess);
Thanks JDP002, it is always good to have 4 eyes on code rather than 2 =D