Weird line on top of sprite with transparent background - c++

So I am trying to add a sprite to my program. It has a weird bug:
As you can see on the top of the image there is a black line. Well, that line should not be there. Also, since I don't get any errors I have no idea where the problem might be.
Here is where I set the blend functions:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// same result: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
My fragment shader:
#version core 330
in vec2 texCoords;
out vec4 frag_color;
uniform sampler2D image;
void main()
{
frag_color = texture(image, texCoords);
}
The image was created in piskel
Could that be a problem in the image itself? I highly doubt it, since I verified that on piskel and also on GIMP, and both reported that it had an alpha channel.
I am also only drawing this object plus the background screen with glClear, which is a rectangle with a texture mapping. Normal textures are working.

Thanks to Reto Koradi I discovered the problem. I was previously using this:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
Now I switched the values to this:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
And it works fine.

Related

Implementing GL_REPEAT on shader

I'm trying to implement GL_REPEAT on glsl. I wrote something using the mod function but there's a problem where the two textures combine. Could you explain why it doesn't work right?
in main:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
my shader code looks like this:
in vec2 TextureCoord;
float yCoord = mod(TextureCoord.y + 0.5, 1.0);
emission = texture(material.emission,vec2(TextureCoord.x, yCoord)).rgb;
//result
vec3 result = emission;
FragColor = vec4(result, 1.0f);
The wrap mode is honored during texture filtering. You set the GL_LINEAR filter mode, hence it will always use a 2x2 texel footprint. If that footprint happens to be at the border, the selected wrap mode will apply to selecting each individual texel. In your case, if you get near the border, you told it to filter into the textrue border color, which a filter with GL_REPEAT wrap mode never would have done, it would have used the texel data from the opposing border instead.
So if you want to re-implement that manually in the shader, you must also implement the texel selection and the filtering itself. Since you also use mipmapping, doing so will be quite complex, and slow.

Texture getting pixelated instead of blurry

I have created a simple OpenGL application.
When zooming into a textured quad, the texture becomes pixelated instead of blurry. I would guess that is due to missing mipmaps?
I create my texture like this:
glGenTextures(1, &mTexture);
glBindTexture(GL_TEXTURE_2D, mTexture);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
And I update it from a PBO like this:
glBindTexture(GL_TEXTURE_2D, mTexture);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, mPboIds[mPboIndex]);
glTexSubImage2D(
GL_TEXTURE_2D,
0, 0, 0,
frame->GetWidth(),
frame->GetHeight(),
GL_RGB,
GL_UNSIGNED_BYTE,
0);
I thought that GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER would tell OpenGL to generate the mipmaps. Ain't that the case?
How can I enable mipmap generation for my texture?
The magnification filter is used when you increase the zoom on a texture, and can have two values:
GL_NEAREST - Returns the value of the texture element that is nearest (in Manhattan distance) to the specified texture coordinates.
GL_LINEAR - Returns the weighted average of the texture elements that are closest to the specified texture coordinates. These can include items wrapped or repeated from other parts of a texture, depending on the values of GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T, and on the exact mapping.
In your case, you are use the wrong magnification filter. It must be GL_LINEAR to minimize the pixelated effect.
MipMaps, for the other hand is used when you want to decrease the zoom and want to get a smooth transition when the texture start to become too far away from the viewer. To get more information about MipMaps, you can look at glTexParameter manual pages, at section GL_TEXTURE_MIN_FILTER, and how to generate in glGenerateMipmap manual page.

OpenGL - How to read Alpha from a texture

I want the alpha value to be read for each pixel from the texture, so that some pixels completely disappear. The texture file(targa format) does contain the proper alpha channel.
Screenshot: http://i43.tinypic.com/2i79s1x.png
Here are the options I am using:
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGR, //changing GL_BGR to anything else doesn't do a thing :? also tried GL_BGRA.
GL_UNSIGNED_BYTE, targaImage);
I have also tried most of the combinations of parameters for the glBlendFunc but none achieves the effect, alhtough I might have skipped it. This is the one that gets the regular blending done right(based on the alpha from glColor):
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Rectangle drawing:
glColor4f(1,1,1,0.5);
mRect->Render();
If I set alpha to 1 it is fully opaque, but there is still white in the bottom right, meaning that the alpha is read from the texture but the white polygon beneath it is visible. So I need to make the polygon disappear somehow, but the texture to remain visible.
So that's how I achieve this in the picture. I have also experimented with this:
glAlphaFunc(GL_GREATER, 0.49);
glEnable(GL_ALPHA_TEST);
It only proves that the alpha of each ,,fragment'' of my rectangle is 0.5.
This texture file has a gradient that has full red around the blue circle in the middle, but the alpha goess from 0 in the top-left to full in the bottom-right(it's not the red color fading to white).
I would supply the whole code but it has more than 2k lines and I have split everything into classes, so I am just pulling out the parts I think are important.
Do I need my own shader to do this? I have only made my first contact with OpenGL and C++ a couple of weeks ago and I'm not into them yet, so if that's the solution I would appreciate a link to a tutorial that deals with alpha and GLSL.
Thank you :)
It looks like you're using the old, fixed function pipeline. With that you must properly configure the texture environment. Specifically you want the texture to modulate or replace the base color. Either is fine, but I presume replace mode is better suited for you.
After binding the texture set the mode using glTexEnvi, in your case specifically
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
Also I want to remind you, that you actually must enable blending (glEnable(GL_BLEND);)
If you look at the reference page for glTexEnv I think you easily grasp how ridiculously complex the state space for the fixed function texture environment pipeline became. I strongly suggest you don't bother with it and go directly for using the programmable pipeline, i.e. fragment shaders. Yes, their learning curve is significantly steeper, but with shaders you can actually write something legible like
#version 330
uniform sampler3D sampler_albedo;
uniform sampler2D sampler_diffuse;
out vec4 outcolor;
main()
{
float albedo = texture(sampler_albedo, texcood);
vec4 diffuse = texture(sampler_diffuse, texcoord);
outcolor = mix(basecolor, diffuse.rgb, diffuse.a) * albedo;
}
instead of spending over 15 lines setting up the texture environment and register combiners.

OpenGL transparency of black background

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).

OpenGL Skybox Issue

There are seems on the edges of the cube that I have constructed and I cant understand why. I have set the following parameters...
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
The lines only appear sometimes, it depends on what angle the camera is sitting at. Any ideas why the lines are still there?
It would help if you could show us a screen shot. But the problem is probably the fact that you're not interpolating the textels along the edge of each face with their neighbors on the other faces.
So you should add a border to each texture by copying the edges of the neighboring textures, and change the filter mode to GL_CLAMP. Or you can use a cubemap texture instead.
maybe you need to add:
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
in the code you provided there is only S and T coord setup, you need the R as well.
Turns out this was actually a problem with SOIL which is the texture loading program that I was using. After I changed the texture loading method the lines dissapeared