I'm working with sprite animation (OpenGL + C++).
I have some trouble working with blending.
I'm trying to load an image with a black background and draw it over another texture without a block of black appearing around the image. The image has Alpha channel and blending is enabled.
I tried playing with different blending functions. I either end up with a blocky image or a translucent image.
I know I can do it if I replace the black background with a transparent color instead using an image editing software, but I would like to get this working without that and without using an image mask.
An example to better understand my situation.
The image & Image over texture done incorrectly:
The way I want it to be:
Here is a bit of code that I'm using. I picked out what seemed to be most relevant since a lot of code is spread out over a few classes.
glEnable(GL_DEPTH_TEST);
....
....
glEnable(GL_TEXTURE_2D);
/*Drawing the image with black background first*/
glBindTexture(GL_TEXTURE_2D, blockImage);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
//drawing code
...
...
...
/*background texture is drawn last*/
glBindTexture(GL_TEXTURE_2D, bgImage);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBlendFunc(GL_ONE, GL_DST_ALPHA);
//drawing code
...
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
I don't really need the actual code to do this. A small explanation of the logic would suffice (order of drawing and blending).
OpenGL fixed-function pipeline has no builtin support for color keying. If you want to do it, you can write a shader to test the fragment's color and use the discard operation.
If you want to do this in fixed-function you'll have to properly use the alpha channel (make all the black area alpha = 0 in pre-processing).
Related
Recently my textures went crazy. Last 2 textures that I tried to map appeared as in the picture below. I want it to appear as in the first picture but no matter what I did, it insists on appearing like in the latter one. Ignore the text please, it has nothing to do with texture.
I am using GLUT for my openGL windowing, and GLM obj loader's tga reader. I used the reader many times before and there was no problem. It just stopped working for my last two attempts to load texture. The related code is below:
Texture onScreenTexture;
if (LoadTGA(&onScreenTexture, "back.tga"))
{
glGenTextures(1, &onScreenTexture.texID);
glBindTexture(GL_TEXTURE_2D, onScreenTexture.texID);
glTexImage2D(GL_TEXTURE_2D, 0, onScreenTexture.bpp / 8, onScreenTexture.width, onScreenTexture.height, 0, onScreenTexture.type, GL_UNSIGNED_BYTE, onScreenTexture.imageData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if (onScreenTexture.imageData)
{
free(onScreenTexture.imageData);
}
}
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, onScreenTexture.texID);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex2f(10.0, 10.0);
glTexCoord2f(0,1); glVertex2f(260, 10.0);
glTexCoord2f(1,1); glVertex2f(260, 110);
glTexCoord2f(1,0); glVertex2f(10.0, 110);
glEnd();
glDisable(GL_TEXTURE_2D);
This is nothing to do with the ratio of width/height (though you do seem to be rendering it 90 degrees rotated, causing some additional stretching), but with the packing of rows of pixels. This is apparent from the diagonal pattern, indicating an progressive alignment issue, and also the coloured stripes, showing that the RGB data is unaligned differently on each line.
In your case, you're loading a TGA, which has no row-padding, but passing it to GL which by default expects rows of pixels to be padded to a multiple of 4 bytes.
Your working textures probably are either 32-bit rather than 24-bit or are a multiple of 4 pixels wide, either of which gives a natural alignment.
Possible fixes for this are:
Change the dimensions of your texture, such that there will be no padding.
Change the loading of your texture, such that the padding is consistent with what GL expects
Tell GL how your texture is packed, using (for example) glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
I load an bitmapfont (as png image) in my openGL Application to render characters from there at a fixed size. That's working. But: If I want to scale some glyphs at a smaller size it doesnt look great. Is there a way - without using pregenerated mipmaps (I have a big bunch of several characters and need stepless sizes) to scale this more beautiful? Some way of interpolation or something?
At the moment I use something like this (C/C++ on Mac OS X):
glPopMatrix();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, texture->getID());
glScalef(0.7f, 0.7f, 0); //scale here a size
{draw vertexes & set texcoords}
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glPushMatrix();
Any suggestion?
Did you try using Linear filtering on your textures?:
glTexParameteri(GL_TEXTURE_2D, GL_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_MAG_FILTER, GL_LINEAR);
This after binding textures.
I noticed that when I'm loading a texture, it might change the current drawing color, depending on the texture's color. For example after executing
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, info.biWidth,
info.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,bitmap);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
all consecutive polygons drawn to the screen will have a color depending on the texture image loaded.
Is that standard? I didn't find this behavior documented.
Yes, it's how it works, remember that GL is a state machine, so you left the texture bound (and probably enabled), so when drawing it used the first pixel (assuming you didn't provide any texture coordinates) to color the primitive.
To solve it, disable texturing when you don't want texturing, you can do it with:
glDisable(GL_TEXTURE_2D);
I have a problem with incorrect alpha blending results with openGL ES on iPhone.
This is my code for creating texture object:
glGenTextures(1, &tex_name);
glBindTexture(GL_TEXTURE_2D, tex_name);
glTextImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, GL_RGBA, GL_UNSIGNED_BYTE, tex_data);
'tex_data' is loaded from raw RGBA8888 data packed with zlib. It loads as it should, wich i've checked with a debugger.
This is my code for setting up texture before rendering:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, tex_name);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
I've uploaded a sample of what I've expected and what I've got here: sample . In the sample most of the texture in the bottom is pitch-black with 70% opacity. However openGL renders it as gray. This problem affects all of my textures I use blend with.
I've tested the code on windows with use of OGLES PVRVFrame and the results are as expected: black is rendered as black.
Found the problem. I've forgot to set opaque property of CAEAGLLayer of EAGLView to YES.
Will this help? glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) I think this just blends the two instead of blending both against the background.
Sorry if I don't understand.
I'm trying to capture the screen to a texture with a lower resolution than the screen itself (to render back onto the screen and create a blur/bloom effect), and it doesn't work quite well. I understand mipmaps can be used to do this, but I just can't get the correct sequence of commands to work.
My current code:
width=1024;
height=1024;
glGenTextures(1, &texture);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, width, height, 0);
// code for rendering the screen back on goes here
You can't capture and downfilter in one go. You have to capture the full screen to a larger texture first, then mipmaps should be created if auto-create mipmaps are enabled, then you can render one using that texture again, makig sure you adjust the mipmap level suitably.
However, that will look ugly, as the auto mipmapgeneration usually uses a box filter.
What I'd do is to set up some FBOs (Frame Buffer Objects) and GLSL shaders instead. That gives you finer control over all steps:
create the original image in a texture
apply some nice gaussian low-pass filtering
blend the filtering with the original image to the frame buffer