OpenGL Blend Function To Copy RBG/Disregard Alpha? - opengl

There may be an easier way to do this, I can do it with a shader I'd imagine, but I feel like setting the blend function is simpler.
Shader would maybe be gl_FragColor = vec4(texture.rgb, 0);
For a reason, I need to have a freshly cleared FBO filled with a transparent (0) texture. That way the pixels in the FBO are visually transparent, but contain the RGB values of the texture.
It's tough to explain, but it's essentially a glClear() but with a texture rather than a solid color. Is there a combination blend src/dst function that would accomplish this?
Basically it shouldn't matter what the FBO looks like beforehand. I then want to render a texture to it, but since I'm rendering it with alpha 0, it's not overriding the existing FBO pixels.

If you really want to do this via blending, you can do this via the separate blend factors introduced originally in GL_EXT_blend_func_separate (promoted to OpenGL core functionalitiy in Version 2.0):
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ZERO, GL_ZERO);
glBlendEquation(GL_ADD); // is the default anyway

Related

Rendering transparent texture onto glTexture

I've been working in opengl for a while relatively smoothly, but recently I've noticed that when I render a primitive with a transparent texture onto my fbo texture (custom frame buffer) it makes the fbo texture transparent at the pixels the primitive's texture is transparent. The problem is that there are things behind this primitive (with solid color) already rendered before the transparent one. So the fbo texture should not be transparent at those pixels - blending a solid & transparent color should result in a solid color, shouldn't it?
So basically, opengl is adding transparency to my fbo-texture just because the last primitive drawn has transparent pixels even though there are solid colors behind it already drawn into the fbo texture. Shouldn't opengl blend the transparent texture with the fbo's existing pixels, and result in a solid color if the fbo texture is already filled with solid colors before rendering the transparent primitive?
What happens when I render my fbo texture to the default frame buffer, is that the clear color bleeds through parts of it - where the last drawn texture is transparent. But when I render the same scene straight to the default opengl frame buffer, the scene looks fine and the clear color is not bleeding into the transparent texture.
What's even more interesting is that the glClearColor - color is only visible where the primitive's texture's alpha has a gradient - the clear color has no influence on where the texture alpha is 1.0 or 0.0... is this a bug? It seems to affect the primitive's texture the most at pixels with 0.5 alpha. Then going further above or below decreases the glClearColor influence.
I know it's a bit of a complex question/situation, I honestly tried my best to explain
I'm using:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
to draw both the partly transparent primitive into the fbo-texture, and then the fbo texture to the default framebuffer
This is what the fbo-texture drawn into the default opengl fbo looks like:
glClearColor is set to red.
blending a solid & transparent color should result in a solid color, shouldn't it?
Only if your blend mode tells it to. And it doesn't:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
This applies the same blending operation to all four components of the colors. This causes the final alpha to be the result of multiplying the source alpha by itself and adding that to the destination alpha times 1-src alpha.
Now, you could use separate blend functions for the color and the alpha:
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
The last two parameters specify the blending for just the alpha, while the first two specify the blending for the RGB colors. So this preserves the alpha. Separate blend functionality is available on GL 3.x and above, but is also available as an extension on older hardware.
But it seems to me that you probably don't want to change the alpha at all. So simply mask alpha writes when rendering to the texture:
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
Don't forget to undo the alpha mask when you want to write to it again.

How do I make my object transparent but still show the texture?

I'm trying to render a model in OpenGL. I'm on Day 4 of C++ and OpenGL (Yes, I have learned this quickly) and I'm at a bit of a stop with textures.
I'm having a bit of trouble making my texture alpha work. In this image, I have this character from Spiral Knights. As you can see on the top of his head, there's those white portions.
I've got Blending enabled and my blend function set to glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
What I'm assuming here, and this is why I ask this question, is that the texture transparency is working, but the triangles behind the texture are still showing.
How do I make those triangles invisible but still show my texture?
Thanks.
There are two important things to be done when using blending:
You must sort primitives back to front and render in that order (order independent transparency in depth buffer based renderers is still an ongoing research topic).
When using textures to control the alpha channel you must either write a shader that somehow gets the texture's alpha values passed down to the resulting fragment color, or – if you're using the fixed function pipeline – you have to use GL_MODULATE texture env mode, or GL_DECAL with the primitive color alpha value set to 0, or use GL_REPLACE.

How to render color and depth in multisample texture?

In order to implement "depth-peeling", I render my OpenGL scene in to a series of framebuffers each equipped with a rgba color texture and depth texture. This works fine if I don't care about anti-aliasing. If I do, then it seems the correct thing to do is enable GL_MULTISAMPLING and use a GL_TEXTURE_2D_MULTISAMPLE instead of GL_TEXTURE_2D. But I'm confused about which other calls need to be replaced.
In particular, how should I adapt my framebuffer construction to use glTexImage2DMultisample instead of glTexImage2D?
Do I need to change the calls to glFramebufferTexture2D beyond using GL_TEXTURE_2D_MULTISAMPLE instead of GL_TEXTURE_2D?
If I'm rendering both color and depth into textures, do I need to make a call to glRenderbufferStorageMultisample?
Finally, is there some glBlit* that I need to do in addition to setting up textures for the framebuffer to render into?
There are many related questions on this topic, but none of the solutions I found seem to point to a canonical tutorial or clear example putting all these together.
While I have only used multisampled FBO rendering with renderbuffers, not textures, the following is my understanding.
Do I need to change the calls to glFramebufferTexture2D beyond using GL_TEXTURE_2D_MULTISAMPLE instead of GL_TEXTURE_2D?
No, that's all you need. You create the texture with glTexImage2DMultisample(), and then attach it using GL_TEXTURE_2D_MULTISAMPLE as the 3rd argument to glFramebufferTexture2D(). The only constraint is that the level (5th argument) has to be 0.
If I'm rendering both color and depth into textures, do I need to make a call to glRenderbufferStorageMultisample?
Yes. If you attach a depth buffer to the same FBO, you need to use a multisampled renderbuffer, with the same number of samples as the color buffer. So you create your depth renderbuffer with glRenderbufferStorageMultisample(), passing in the same sample count you used for the color buffer.
Finally, is there some glBlit* that I need to do in addition to setting up textures for the framebuffer to render into?
Not for rendering into the framebuffer. Once you're done rendering, you have a couple of options:
You can downsample (resolve) the multisample texture to a regular texture, and then use the regular texture for your subsequent rendering. For resolving the multisample texture, you can use glBlitFramebuffer(), where the multisample texture is attached to the GL_READ_FRAMEBUFFER, and the regular texture to the GL_DRAW_FRAMEBUFFER.
You can use the multisample texture for your subsequent rendering. You will need to use the sampler2DMS type for the samplers in your shader code, with the corresponding sampling functions.
For option 1, I don't really see a good reason to use a multisample texture. You might just as well use a multisample renderbuffer, which is slightly easier to use, and should be at least as efficient. For this, you create a renderbuffer for the color attachment, and allocate it with glRenderbufferStorageMultisample(), very much like what you need for the depth buffer.

OpenGL blend two FBOs

In a game I'm writing, I have a level, which is properly rendered to the on-screen render buffer provided to me by the OS. I can also render this to a framebuffer, then render this framebuffer onto the output render buffer.
To add a background, I want to render a different scene, an effect, or whatever to a second framebuffer, then have this "show through" wherever the framebuffer containing the level has no pixel set, i.e. the alpha value is 0. I think this is called alpha blending.
How would I go about doing this with OpenGL? I think glBlendFunc could be used to achieve this, but I am not sure how I can couple this with the framebuffer drawing routines to properly achieve the result I want.
glBlendFunc allows the application to blend (merge) the output of all your current draw operations (say, X) with the current "display" framebuffer (say, Y) that already exists.
ie,
New display output = X (blend) Y
You can control the blend function by gl as below snippet shows for example:
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Full usage shown here
https://github.com/prabindh/sgxperf/blob/master/sgxperf_test4.cpp
Note that the concepts of "showing through" and "blending" are a little different, you might just want to stick with "per pixel alpha blending" terminology.
FBOs are just a containers and are not storage. What you need to do is attach a texture target for each FBO and render your output to that texture, once you have done this. You can use your output textures on a fullscreen quad and do whatever you want with your blending.

OpenGL FBO - White pixels appear transparent

I'm making a 2D game using OpenGL. I recently tried implementing Framebuffer-objects, and I am having some problems regarding blending.
I'm creating an FBO (using GL_RGBA as format).
When I render to the FBO, I first clear it to fully transparent black, and disable GL_BLEND. I then draw my textures and then I enable GL_BLEND again.
When I'm drawing the FBO-texture, I use GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA as source and destination pixels respectively, as the blending-function. I am rendering it as a textured quad.
This does not work properly, as white pixels appear transparent. I have tried experimenting with different blend-function values, but all that I have tried have had issues. I do not fully understand how blending works, so it's hard for me to wrap my head around this. Maybe I'm missing something obvious here?
Here's an image of how it looks right now. There is supposed to be a glow around the button when it is being highlighted, but instead the pixels around it appear transparent: http://i.snag.gy/RnV4s.jpg
You can also see two boxes of text in the image. The top one is drawn normally, without an FBO. The textures are also rendered normally without an FBO, so I know that the problem lies within my framebuffer-code somewhere.
I have pasted my "RenderTarget" class to pastebin (I'm used to calling it a rendertarget instead of FBO): http://pastebin.com/dBXgjrUX
This is how I use it:
RT->Begin();
// draw stuff
RT->End();
RT->Draw();
Can someone help me? Let me know if you need any more info about my issue.
Edit:
Here are the properties of OpenGL that I set on startup:
// Initialize shaders
shaderManager.InitializeStockShaders();
// Set some OpenGL properties
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel(GL_SMOOTH);
glAlphaFunc(GL_GREATER, 0.0f);
// Enables/disables
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_DITHER);
glDisable(GL_LIGHTING);
I'ts a bit difficult to tell what your problem is exactly, because you didn't provide source code. Alas, I see several potential troublemakers:
First you told that you want to draw a glow around the button. I presume, that all the buttons are drawn into the FBO, merging them into a UI overlay. Glow sounds to me, like you want to blend something, so you probably also want to have blending enabled, drawing to the FBO.
Next be aware of depth buffer issues. Blending and Depth Buffering have peculiar interactions. In your case I suggest disabling depth testing and depth writes to the FBO (or not using a depth buffer attachment to the FBO at all). Draw the glowing button last, so that it won't block the other buttons from being drawn. Also you must make sure, that your glow comes out with a nonzero alpha value, otherwise it will blend transparent. This is something you control in your shaders, or texture environment (depending on what you use).
Update 1:
Your FBO class doesn't propperly ensure, that textures attached to a bound framebuffer must not be bound themself. It's easy to fix though, by moving attachment code into bind, where the textures are also unbound apropriately. See my edited pastebin http://pastebin.com/1uVT7VkR (I probably missed a few things).