Removing OpenGL texture artifacts - opengl

I am creating a simple opengl application which obviously includes some 3d-objects and textures. My problem is however that artifacts appear on every texture. These come in the form of triangles along the edges.
I have noticed that it disappears as soon as I move the view-point closer to texture it renders perfectly. Therefore I have a suspicion that it has something to do, either with the mipmapping or the z-buffer.
Please note that all texture-coordinates are loaded from a .3ds-file and all of them are verified to be within the range of 0-1.
Here are a picture of my problem:
Picture 1
The textures are loaded like this:
//Texture parameters
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//Define the 2d texture
glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, array);
//Create 2d mipmaps
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, GL_RGBA, GL_UNSIGNED_BYTE, array);

When I was programming using DirectX, the near plane / far plane distance ratio caused artifacts in the edges.
In my case, if near plane was 1 unit away from 'camera' and far plane was 10000 units away, the ratio is 1/10000 and it created problems. If i set the near plane to 10 or 100, the ratio becomes bigger. It solved the jagged edges problem.
I don't know if/how it is applicable in OpenGL, but you might want to check it out.

Related

How to set texture parameters in OpenGL/GLFW to avoid texture aliasing (wavey behavior on object borders) when viewing objects from a distance?

I am rendering a huge 3D cube array, that sometimes counts thousands of cubes aligned right next to one another. I am rendering a jpg texture to the cubes, which is just a simple color with a black border around the frame.
The problem:
The array is huge, and the distant parts of the array get kind of mixed into one another, so to say. In other words, the borders in the distant cubes sometimes completely disappear, sometimes they form an arbitrary wavey line together with other neighboring borders. All in all, the scene looks kind of messy because all the fine details (hard borders between the neighboring cubes) are lost/melted together. After searching for the solution online, I understand that the problem might be in my choice of texture filtering options.
This is how the problem actually looks like in OpenGL:
This is how the current code for loading texture and setting texture parameters looks like:
glGenTextures(1, &texture3);
glBindTexture(GL_TEXTURE_2D, texture3);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//load image:
data = stbi_load("resources/textures/gray_border.jpg", &width, &height, &nrChannels, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
By now, I have tried playing with changing different parameters to the function glGenerateMipmap() and altering between the parameters in the glTexParameteri() function, but none did work by now.
If you want to enable Mip Mapping, then you have to use one of the minifying functions like GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR, see glTexParameter and Texture - Mip Maps:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
A further improvement can be gained by Anisotropic filtering, which is provides by the extension ARB_texture_filter_anisotropic and is a core feature since OpenGL 4.6.
e.g.
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, 16);
See Sampler Object - Anisotropic filtering

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.

Textures Stopped Working Correctly

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

OpenGL CubeMap Texture Dimensions

After struggling all weekend, I finally have a sphere reflecting its environment in OpenGL. It almost looks good. Problem is, certain features don't line up. I can't find much information on the topic of OpenGL sphere mapping, outside of a two page section in the Red Book and a few scattered, and mostly unfinished forum topics. Not sure it's necessary, but I included my code where I load the textures. After trial and error, I found that having symmetrical dimensions freom 0 to 512 gets the best results, but they still aren't perfect (and the dimensions have to be powers of two, or it crashes). Does any one know of any strategies to get textures that line up more correctly?
void loadCubemapTextures(){
glGenTextures(1, &cubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
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_WRAP_R, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glDrawBuffer(GL_AUX1);
glReadBuffer(GL_AUX1);
glMatrixMode(GL_MODELVIEW);
//Generate cube map textures
for(int i = 0; i < 6; i++){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//Viewing Transformation
gluLookAt(pos[0], pos[1], pos[2],
view_pos[i][0], view_pos[i][1], view_pos[i][2],
top[i][0], top[i][1], top[i][2]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.0, 1.0, cubemapRadius + 1, 200.0);
glMatrixMode(GL_MODELVIEW);
render();
glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, 0, 0, 256, 256, 0);
}
Your walls lack enough features to make their orientation and location clear, but I would bet those are the issue.
The values you have in view_pos and top are what define those. Among the things that look suspicious:
the black at the bottom of the shere comes from the face that captured the front view. It should be at the top (ie it's either flipped, or rotated 180).
likewise, the black that comes from the back of the view (in the center of the sphere) looks turned by a quarter of a circle (as black goes on the left rather than being on the top).
the reflection of the map sphere looks weird. It lacks resolution to figure out exactly what this is.
Anyways, to fix it, you can either make sure your values are what is expected from a proper cube-map definition (as in check all the specification), or just do a bunch of trial and error, after adding enough geometry to figure out what the orientation of each face is.
The problem had nothing to do with coordinates, thanks for the input though. I had forgotten to set the view matrix... a simple call to gluViewport inside the for-loop fixed it for me.

OpenGL: Loading a texture changes the current color

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