Texture Aliasing problem while rendering large chunks: OpenGL - c++

Texture rendering is good without any texture error when the world size is small, but when it increased to some extend then it shows texture error. tried several texture mapping techniques but none helped(or may be I am doing it wrong)
The issue is similar with shadow acne but it not shadow acne(That i am sure), as I haven't implemented any shadow mapping yet.
Don't know how to solve this one, any help would be appreciated(or what i am doing wrong).
(Attaching the shader code for reference)
out vec4 FragColor;
in vec2 ChunkTexCoords;
uniform sampler2D sampler;
void main() {
FragColor = texture(sampler, ChunkTexCoords);
if(FragColor.a == 0) discard;
}
Texture parameters
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE
);
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE
);
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER,
GL_NEAREST
);
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER,
GL_NEAREST
);

Your texture minification filter is nearest neighbor box sampling. As soon as the sampling frequency falls below half the highest spatial frequency in your texture (the so called Nyquist frequency) you're going to get sampling aliasing artifacts.
The solution: Create complete set of mipmap levels that are properly low pass filtered.

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.

How to properly map a 2D image texture to an icosphere

I'm programming a simple graphics engine in C++ that should be capable of representing the Earth. The Earth is modelled as an icosphere, and I planned to map its texture using the normals of each vertex. To do so, I'm essentially trying to get vertical and horizontal coordinates (φ and θ, respectively) (i.e. latitude and longitude) from the vertices' normals.
The following is the (edited) function that implements my approach (called when new vertices are generated). It should return texture coordinates from (0,0) to (1,1) when the parameter n is a normal vector:
glm::vec2 Icosphere::getTexCoord(glm::vec3 n)
{
float theta = (atan2f(n.x, n.z) / PI) / 2.f + 0.5f;
float phi = (asinf(-n.y) / (PI / 2.f)) / 2.f + 0.5f;
return glm::vec2(theta, phi);
}
However, this is yielding unexpected results. With this test image, my icosphere looks like this:
Small white and red triangles are located at (x,y,z) = (1,0,0). In the first image, I generated the icosphere with less triangular faces (320), whilst in the latter the icosphere is generated with ~82k triangles.
I'm suspecting that what causes those texture "glitches" is the fact that coordinates (0,*) and (1,*) are not considered adjacent. Is there a proper way of doing this?
NB: These are my texture parameters:
/* Configure texture parameters: */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
I finally managed to overcome this ugly texture mapping. The problem is indeed caused by the characteristic non-uniform orientation of triangles in an icosphere. In an icosphere (as well as in an icosahedron) it is impossible to find a plane in the origin (0,0,0) that does not intersect any triangle. If we think of the Earth, this means that all its meridians intersect some triangles. It also means that when mapping a texture, the triangles located in the texture vertical edges (i.e. with tex. coord. (1,y) and (0,y)) will have some of their vertices in either of the sides. When this happens, the texture is interpolated from x≈1 to x≈0, producing the effect showed in my images.
In order to solve this, I set the texture wrapping to GL_REPEAT and simply forced some vertices to be away from the texture coordinate space (i.e. x > 1). This allowed the texture edges to be adjacent and mapped the texture perfectly:
/* Configure texture parameters: */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Not GL_CLAMP_TO_EDGE.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Not GL_CLAMP_TO_EDGE.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
Results:
After modifying texture coordinates of triangles in the edges (with GL_CLAMP_TO_EDGE):
Changing texture parameters to GL_REPEAT:

Weird line on top of sprite with transparent background

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.

Texture edges are moving when camera is moved

The textures look good as long as the camera remains in a fixed position and rotation. However, when the camera is moving or rotating, (partial) lines appear between textures. I think it has to do something with subpixel correction. The texel is switching between the previous and the next one.
For my textures I use:
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_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 same problem appears when using GL_NEAREST.
The fragment shader uses simple texture lookups:
color = texture( textureID, UV );
Or maybe this is an aliasing problem?
Edit - image
Edit - UV image: same problem
Edit Normals as colors
It looks like the depth is not sorted well.
I am using perspective projection.