开发者

Using alpha from texture to draw solid color

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 looki开发者_开发技巧ng 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.


glBlendFunc(source_factor, dest_factor) translates to:

dest= source*source_factor + dest*dest_factor

So glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA) is:

dest= source*0 + dest*(1 - source.alpha)

The second pass (which isn't the inverse) should be glBlendFunc(GL_SRC_ALPHA, GL_ONE):

dest= source*source.alpha + dest

since you already applied the alpha mask in the first pass. Although you still need to figure out how to apply a constant color with alpha instead of the source texture.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜