I am working on engine (http://b2dengine.com/) to implement my game idea, which is already in progress. Now for quite a while I am stuck with this problem with text rendering.
I have texture atlas that contains all supported/needed characters in a single png image. Character mapping is defined by Font class.
Everything works fine, characters are rendered correctly and accurately. Thing is that I also need ability to change color of the text.
This sounds and I bet it is simple but I cant make it work.
I am using this gl blend function to get desired effect.
GL.instance.glBlendFunc(GL.instance.GL_SRC_ALPHA, GL.instance.GL_ONE_MINUS_SRC_ALPHA);
In most cases it works, well as long as the color is somewhat dark. But when its set to white, I can see artifacts. I can provider screenshot if needed.
Also for this to work, "text" in texture must be white.
I am using opengl 1.1 ( yes I know its old, but I am just not ready for shaders ).
So in short, my question is: how to render a texture and completely replace the color? Keeping only alpha channel.
E.g. if its black and 80% transparent in png, when I render I want it green at 80% transparency on screen.
I think this will work, though these are some anciently deprecated functions and I don't remember too much about them anymore.
With your texture unit active which has the text texture, try setting these options:
glTexEnv(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnv(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnv(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR);
glTexEnv(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
I believe this will replace the RGB of your fragment with the incoming fragment color (glColor), and completely ignore the RGB channel of the texture. Having said this, it would be a lot better if you just uploaded an alpha channel texture to begin with.
Make sure to check for errors, and if it doesn't work, you can see if I've grabbed something incorrectly from here: http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml
Related
I'm drawing text from a texture atlas containing an alphamap GL_ALPHA, GL_UNSIGNED_BYTE --- it's produced by stb_truetype, if that's any help. Right now I'm drawing with GL_BLEND enabled and the texture with all the default settings. I can set the foreground colour with glColor3f, the background is transparent, and everything works fine.
The problem is, on some platforms drawing transparent text is too slow. And I don't actually need it; the background is always a solid colour. I am, in fact, filling it with glRectf just before drawing the texture.
Experiments have shown that disabling GL_BLEND fixes all my performance issues, but of course that gives me solid blocks of colour instead of text. Looking at the documentation for glTexEnvi, it seems to me that it ought to be possible to draw the texture without blending, getting it to just apply the alpha value to fixed source and destination colours. But I can't figure out how, the documentation is rather opaque, and just trying stuff isn't helping.
(Maybe I need to have GL_BLEND enabled but tell it somehow to use my background colour rather than reading from the framebuffer?)
Can anyone enlighten me?
I am using old-fashioned fixed-pipeline pre-shader OpenGL, by the way, so I can't simply do all this in the shader fragment.
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.
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).
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...
I'm trying to work with the FTGL font library, to create a texture-mapped font and render it to the screen. The library creates a texture in the GL_ALPHA format to hold the font glyphs, and then when you tell it to render a string, it goes through and glBegin(GL_QUADS) and renders each glyph, exactly how you'd expect.
Only problem is, I'm not getting any text. In one scenario, I get solid black boxes instead of text, in another I get nothing. I've run the code under gDEBugger to ensure that the texture is getting uploaded and set up properly, and everything looks right, but I'm still not seeing any output.
I've tried the obvious stuff. Calling glColor beforehand to try to set a text color does nothing. Neither does attempting to ensure that alpha-blending will work properly, like so:
glEnable(GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Does anyone have any idea what I'm missing, in order to make rendering from a GL_ALPHA texture to the screen show up properly?
It's clear after an examination of FTGL's code that the API is designed to do the text rendering itself. You're expected to call its rendering functions, which will make the OpenGL calls internally.
To put it another way, FTGL is not designed to load a font into a texture, then give you that texture object and have you draw the glyphs yourself. That doesn't mean you can't, only that the API is not going to help you do it.
The reason you get black is because GL_ALPHA textures return zeros for the RGB component when accessed. Since you use GL_MODULATE in your texture environment, that's going to multiply zero by the RGB part of the color.
To do what you intend, you need to set the GL_TEXTURE_ENV_MODE to GL_COMBINE instead of GL_MODULATE. Which means you need to use the combine environment mode, which isn't simple. Having abandoned fixed-function for shaders pretty much as soon as they existed, I haven't touched combiners in a long time. So take what follows with a grain of salt. Here's a guess at what the environment code should look like:
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_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
What you want to do is generate a color where the RGB part comes from glColor and the Alpha part comes from the texture. This is how you do that.
In English, the first line says that the texture environment mode is "combine", which activates a more complicated operation mode. The next three lines specify how the RGB part of the color is generated. The GL_COMBINE_RGB set to GL_REPLACE means that the source RGB value 0 will be what the output RGB is. Setting GL_SRC0_RGB to GL_PRIMARY_COLOR means that source RGB value 0 is the primary color, which is the color generated by vertex processing (ie: unless you're using lighting, this is just what you passed with glColor). Setting GL_OPERAND0_RGB to GL_SRC_COLOR means to take the color as it is (there are special operations you can do, like take 1 - the color or whatever).
The next 3 lines set up where the alpha part of the output color comes from. The GL_COMBINE_ALPHA set to GL_REPLACE means that the source alpha value 0 (different from the source RGB value 0) will be what the output alpha is. Setting GL_SRC0_ALPHA to GL_TEXTURE means that the source alpha value 0 comes from the texture of the current texture unit. Setting GL_OPERAND0_ALPHA to GL_SRC_ALPHA means to take the alpha as it is (as before, you could apply some transform to the alpha here).
Alternatively, if your OpenGL implementation has ARB_texture_swizzle available, you can set up a swizzle mask to effectively transform the GL_ALPHA format into GL_INTENSITY. Then you can use GL_MODULATE as your GL_TEXTURE_ENV_MODE. However, you have to make sure that your blend mode is glBlendMode(GL_ONE, GL_ONE_MINUS_SRC_ALPHA). This is necessary because GL_MODULATE will multiply the color by the alpha. If you used GL_SRC_ALPHA instead of GL_ONE, you would be doing the multiply by alpha twice (once in the texture env stage, once in the blend stage).