How can I use OpenGLES 1.1 (iPhone) to draw a texture, but only using the alpha to draw some color?
The result should be the exact same alpha mask from the original texture, with a single solid color inside instead of the original colors.
I am using glDrawArrays
with glCoordPointer
and glVertexPointer
.
I think doing two passes, one with the texture and one with a solid color to to this. I just can't seem to find the invert of glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
.
Edit: after some more looking around, I thinks this should be possible to achieve using glTexEnvf
. It's just a matter of finding the right arguments.
As mentionned, glTexEnv is the way to go.
To replace the RGB components of your texture and keep its alpha untouched, you could try something like this (this code uses red as replacement color):
glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
glActiveTexture( GL_TEXTURE_0 );
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, spriteTexture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
// ... draw as usual
Here come some explanations.
When using GL_COMBINE, you have complete control on how the input/output of the different texture stages are combined together. In this case, we specify that we want to replace (GL_REPLACE) the RGB components of texture stage 0 with what comes from the previous stage (GL_PREVIOUS) which in this case is a single color (set with glColor4f).
We did not set anything special for the alpha component as we want the regular behavior. Adding the following lines would have had the same effect as if not included (default behavior):
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
If you can use OpenGL ES 2.0, you could do this with a custom fragment shader. If you're using a framework that is built on 1.1 or are targeting devices that don't support 2.0, this won't be much help. But if you can, this is how you do it:
uniform lowp sampler2D sampler; // which texture unit to use
uniform lowp vec4 solidColor;
varying highp vec2 fragmentTexCoord;
void main()
{
// Get the color with an alpha of zero
vec4 color = vec4(1,1,1,0) * solidColor;
// Get the alpha from the texture, zero the r,g,b components
vec4 alpha = vec4(0,0,0,1) * texture2D(sampler, fragmentTexCoord);
// their sum is the solid color with the alpha mask of the texture
gl_FragColor = color + alpha;
}
If you can ensure the solidColor has an alpha of zero you could skip the multiplication step.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With