I am trying to create a scrolling list in OpenGL ES 2.0 on Android and I want the contents of my list to fade out as the list reaches the top or bottom. Right now I am implementing this in a fragment shader but it is very slow.
Here is my shader
precision mediump float;
uniform bool uEnableTexture;
uniform sampler2D uTexture;
uniform bool uEnableFade;
uniform float uTopFade;
uniform float uBottomFade;
uniform float uFadeWidth;
varying vec4 vPosition;
varying vec2 vTexCoord;
varying vec4 vColor;
void main(){
if (uEnableTexture) {
gl_FragColor = texture2D(uTexture, vTexCoord) * vColor;
} else {
gl_FragColor = vColor;
}
if (uEnableFade) {
if (vPosition.y > uTopFade) {
gl_FragColor = gl_FragColor * 0.0;
} else if (vPosition.y > uTopFade - uFadeWidth) {
gl_FragColor = gl_FragColor * (1.0 - (vPosition.y - (uTopFade - uFadeWidth)) / uFadeWidth);
} else if (vPosition.y < uBottomFade) {
gl_FragColor = gl_FragColor * 0.0;
} else if (vPosition.y < uBottomFade + uFadeWidth) {
gl_FragColor = gl_FragColor * (1.0 + (vPosition.y - (uBottomFade + uFadeWidth)) / uFadeWidth);
}
}
}
This is the effect I am trying to achieve.

Is there a more efficient way to achieve this?
EDIT: I was able to improve this a lot by using separate programs and using this shader only when I needed the fade.
void main(){
gl_FragColor = texture2D(uTexture, vTexCoord) * vColor;
if (vPosition.y > uTopFade - uFadeWidth) {
gl_FragColor = gl_FragColor * (1.0 - (vPosition.y - (uTopFade - uFadeWidth)) / uFadeWidth);
} if (vPosition.y < uBottomFade + uFadeWidth) {
gl_FragColor = gl_FragColor * (1.0 + (vPosition.y - (uBottomFade + uFadeWidth)) / uFadeWidth);
}
}
I could probably speed it up a little more by splitting this into two more shaders, one for the top and one for the bottom, or use uFadeWidth to determine the direction.
Your best bet would probably not to do the math in shader, but to precompute a ‘fade texture’ that would be 1 pixel wide, and as ‘tall’ as your viewport.
In this texture, you could store the fade value for every screen y.
Then, in your shader, you’d be left with another
texture2Dcall, and a multiply.