Do i need Alpha channels for transparency to work in OpenGL? can i use glBlendFunc or anything else to make somehow the Black or White color transparent/not visible? if yes, how to do it?
No, you don't need an alpha channel in your textures. Call discard in your fragment shader for all fragments that match your transparency rule.
Yes, you need alpha channels to use transparency. You can emulate the behaviour of color keying using shaders, or processing the image and replacing the color key with pixels with alpha = 0.0.
Notice that GPUs always allocate RGBA textures, even if you want a RGB texture. The alpha channel is still present in hardware.
Related
I am trying to blend a white texture with varying alpha values with a colored background. I am expecting the result to retain colors from the background, and have alpha values replaced by ones from the blended texture.
So, for background I use:
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendEquationSeparate(GL20.GL_FUNC_ADD, GL20.GL_FUNC_ADD);
Gdx.gl.glBlendFuncSeparate(GL20.GL_ONE, GL20.GL_ZERO, GL20.GL_ONE, GL20.GL_ZERO);
I expect the background triangles mesh to override the destination, both color and alpha.
Question 1 - why with those blendFunc parameters, alpha value is being ignored?
If I set blendfunc to GL_ONE, GL_ONE, GL_ZERO, GL_ZERO then the filled mesh is rendered with proper alpha level - but both the source and dest alpha are supposed to be multiplied by zero - why does this work?
====
Now to blend the alpha map I use:
Gdx.gl.glBlendEquationSeparate(GL20.GL_FUNC_ADD, GL20.GL_FUNC_ADD);
Gdx.gl.glBlendFuncSeparate(GL20.GL_ZERO, GL20.GL_ONE, GL20.GL_ONE, GL20.GL_ZERO);
Question 2 - This supposed to keep the destination color and replace alpha. However, when I render the texture with those blendfunc params, I get no change to the output at all...
I've been reading the opengl blending chapter over and over again to understand what I fail to understand, please, share your insight on how those parameters actually work
I use this:
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
It works but only in the order of rendering. In order to account for depth you will need alpha testing which libGDX does not include.
I am trying to draw brush strokes made of quads with a rough texture into framebuffers that are then composited together. The problem is that the framebuffer texture initial color is 0,0,0,0 and it blends in creating a dark glow around the edges. here is an example image
im using
gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD );
gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.SRC_ALPHA, gl.ONE );
I think Iv tried every possible combination of blending settings and none work the way I want.
here is a demo of the problem
This looks like a pre-multiplication issue to me. Either your brush stroke textures aren't pre-multiplied and they should be, or they are pre-multiplied and they shouldn't be - I forget which.
For compositing you most likely want to use pre-multiplied alpha to get the effect you want. Either pre-multiply the texture when you upload the data
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
or pre-multiply in the shader
gl_FragColor = vec4(color.rgb * color.a, color.a);
And blend with
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
A quick google of "pre-multiplied alpha blending" brought up this great explanation of the issue
Is it possible to draw a RGB texture as grayscale without using fragment shaders, using only fixed pipeline openGL?
Otherwise I'd have to create two versions of texture, one in color and one in black and white.
I don't know how to do this with an RGB texture and the fixed function pipeline.
If you create the texture from RGB source data but specify the internal format as GL_LUMINANCE, OpenGL will convert the color data into greyscale for you. Use the standard white material and MODULATE mode.
Hope this helps.
No. Texture environment combiners are not capable of performing a dot product without doing the scale/bias operation. That is, it always pretends that [0, 1] values are encoded as [-1, 1] values. Since you can't turn that off, you can't do a proper dot product.
I'm working on creating a transparent GUI in OpenGL, and am trying to get text rendered over some semi-transparent quads, but the results are odd.
If I render the text by itself, with nothing behind it, it looks fine:
However, if I render a semi-transparent quad behind it (rendering the quad before rendering the text), I get this:
I have blending set to (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). The font texture is an all-white texture with the character shapes in the alpha channel.
Do I need to be doing something special when performing alpha-transparency over an existing layer of transparency? Or is there something else I need to check?
The alpha value of your font texture seems to be off. It should be 0 for texels that you want to be invisible and 1 (or 255 in bytes) for visible texels. You should check the texture and make sure alpha values are correct.
Instead of alpha blending, you can use alpha testing. This will completely get rid of fragments, that have a alpha value below a certain threshold and is often much faster than blending.
glDisbale(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.96f); // Or some fitting threshold for your texture
This might work even if your texture's alpha is off in some places, but doesn't look like it is the case here, as the 's' and 't' seem to have a low alpha in places where it should be 1.
Thanks for the responses. There was nothing wrong with my font texture, but your suggestions led me to try a few other things. Turns out the problem wasn't the transparency at all. There was a problem with rendering the background quad, which caused it to also render the text quads, but using the background texture. Bah...
Can anyone give some clues as to why when I try to render the color bar quad below
It appears like this:
Here is my rendering code:
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_ONE, GL.GL_ZERO);
gl.glBlendEquation(GL.GL_FUNC_ADD);
gl.glEnable(GL.GL_ALPHA_TEST);
gl.glAlphaFunc(GL.GL_GREATER, 0.01f);
// do the drawing...
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glDisable(GL.GL_ALPHA_TEST);
I'm sure the solution is simple and I'm just having a brainfart but it's just one of those days!
Thanks for the help!
What kind of blending are you trying to perform? To simply draw something without any color mixing or alpha channels you don't even have to play around with GL_BLEND or GL_ALPHA_TEST (leave both disabled). GL_BLEND is used to define how to add different "layers" of color (usually on how to apply alpha channels) while GL_ALPHA_TEST decides what alpha values to respect/ignore. Also check your vertex colors when rendering the quad (try to render a unicolor quad without texture, e.g. using magenta).
However looking at your images I'd guess you somehow disabled drawing to your red color channel (glColorMask()) - although there's yellow, which confuses me.
There was a problem with RGBA getting swapped around when I imported the PNG file.