I'm trying to make an old game look a bit better, it uses opengl version 1.1, as you can see, this in a comparison between how the image looks on photoshop vs how it looks ingame.
As you can see on the right (ingame) the borders are blurry, not as sharp as the original image. (Please ignore all the text).
Is this expected because of the old version of opengl? Or is it something that could be fixed?
It looks like you have some sort of filtering enabled on your texture. Look for GL_LINEAR in your code and replace it with GL_NEAREST
glBindTexture(GL_TEXTURE_2D, texBuff);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Related
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
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.
Lately, while getting used to C++ (already knowing OpenGL * fairly * well), I've gotten tired of the visual artifacts I see with textures at a distance, especially with large flat surfaces such as terrain. When coding in Java and OpenGL, I saw the same issues as well. Here's what I'm talking about:
I load my textures using the GL_COMPRESSED_RGBA_S3TC_DXT1_EXT (with DXT3 and DXT5 as well) extensions in OpenGL loading, obviously, .DDS images. Each image has 11 mipmaps (1 full-res texture and 11 lower-res textures), each of which are generated with bilinear in Paint.NET. The grass texture in this (where you see most of the artifacts) is 2048x2048. I AM using OpenGL 3.3, with shaders powering almost everything, so I can edit stuff in GLSL.
Image Parameters are as follows
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_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 11);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16);
In the GLSL Shader, I call texture2D(grassTexture, terrainTexcoord * 512.0f); The '* 512.0f' is so that the grass isn't stretched all over the entire chunk (I'm using chunks w/ heightmap). The sampler is just a generic sampler2D.
And if anyone's wondering, I got the code for the DDS loader from http://www.opengl-tutorial.org/ (best site ever for OpenGL 3.3+ BTW)
I've probably given more can than what's needed but I hate hearing the "Can I see some more code?" Here's what I'd like to know, what is this effect called? What is a good way to fix it? Is there an post processing effect that takes care of this? Am I doing something wrong? (probably the latter, but oh well xD) Thanks!
If I use the fixed pipeline, I can use
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
to make an image 'pixelated' as opposed to fragments in between pixels in the image being interpolated. How would I do the same thing in GLSL program? I'm using the texture2D function. I ask because I am using a shader program for my skybox, and you can see the edges because the edge pixels get blurred with grey. This problem gets fixed if I were to use the fixed pipeline and the above function calls.
You can use the same texture minification and magnification filters with the programmable pipeline. It sounds like the issue is not the min/mag filter, but with how you're handling texture clamping/wrapping. Either that or your textures have gray in them, which you probably don't want.
To set up texture clamping, you can do the following:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
This will cause any pixels sampled from outside the texture to return the same color as the nearest pixel within the texture to that sample location.
As the other answers and comments alread pointed out, the texture sampling states will effect both the fixed function pipeline and the programmable pipeline in the same ways. I'd just like to add that in shaders, you can also completely bypass the sampling and use the GLSL texelFetch() functions where you can directly access the unfiltered texels - which will basically look like GL_NEAREST filtering. You will also lose the wrapping functionality and hve to use unnormalized integer texture coords, so this is probably not what you want in that scenario, though.
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