简体   繁体   中英

Using blending to create multiple areas of transparency surrounded by black

I've been playing around in openGL a little bit and I was wondering how I can take an image (say for example a black background) and then render a smaller white gradient over the top but have it make the white gradient transparent (instead of white) and remove from the black background. Leaving a black background with a transparent gradient in the center. I'm using LWJGL if that helps.

Is there any way of doing this with blending?

Edit: Okay, is there any way of instead of subtracting two images, I draw black around an image? So I have my white gradient, change it to be transparent and then draw black all around that?

Fixed function is usually implemented using shaders in modern GL drivers (there are old ATI's presentations with SM2.0+ shaders for all of the fixed functionality).

The close-to-trivial blending fragment shader like this

in vec2 TexCoord;

uniform sampler2D Texture0;
uniform sampler2D Texture1;

out vec4 out_FragColor;

void main()
{
     vec4 Color = texture(Texture0, TexCoord);

     /// The mask contains (R,G,B,A) - image + transparency
     /// for both the mask and the source
     vec4 Mask  = texture(Texture1, TexCoord);

     /// Mask is also significant as a color source, not only the alpha
     out_FragColor = Color * ( 1.0 - Mask.a ) + Mask * Mask.a;

     /// Thanks to Tim's comment, the last line can be done simpler:
     /* out_FragColor = mix(Color, Mask, Mask.a); */
}

should mix the image the way you want to.

This is not overkill for modern hardware and it is 100% compatible even with the GL ES 2.0 hardware.

EDIT:

The image from one of my projects (simple mask used to create the fade-away reflection).

We use this mask

阴影面具

and get the final result in this image: Gallery

It may be possible to achieve what you want in the specific case, but in general once you 'draw a black background', there's no way to make it transparent afterward. You can't remove or erase pixels that have already been drawn.

If you can draw the gradient before the black background, then you can deposit the alpha into the framebuffer, and then sample the destination alpha when you draw the black background afterward. You'll need to have a real alpha texture though, as you can't really convert a white gradient to an alpha gradient at draw time.

Here's my suggested pseudocode:

  1. draw whatever you want in the background
  2. create texture with alpha gradient
  3. lock color channels with glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_TRUE);
  4. draw alpha gradient over background
  5. unmask color channels with glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
  6. draw 'black texture' with following blend options: glBlend(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA)

That should leave you with a black texture with a blended gradient to whatever was underneath it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM