I'm having some trouble with a render-to-texture operation. I create a FBO, attach a texture, render to it, and everything's fine, but when I try to change the attached texture, either to 0 or to a new handle, by calling glFramebufferTexture2DEXT again, the texture I had attached becomes blank (all pixel values reset to (0, 0, 0, 0)).
The documentation doesn't say that this is supposed to happen, and it's a bit troublesome for me because I need to retain the information in this texture. Does anyone know why this is happening, and how to prevent or work around it?
Just ran into a nearly the same situation. The end solution was when we were creating the texture we had to make sure to set up the TexParameters.
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
According to https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexParameter.xhtml, GL_TEXTURE_MIN_FILTER defaults to GL_NEAREST_MIPMAP_LINEAR but we weren't mipmapping. I am not sure why that would cause the texture to appear to be erased, but that is what we did to fix it.
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.
I've been having a very weird issue with my project's texture generation. The first mipmapped texture works flawlessly but the next ones only draw the first level. While debugging I suddenly came to a hack that fixes it:
glGenTextures(1, &texture->textureID);
glBindTexture(GL_TEXTURE_2D, texture->textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexStorage2D(GL_TEXTURE_2D, 10, GL_RGBA8, width, height);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glGenerateMipmap(GL_TEXTURE_2D);
assert(glGetError() == GL_NO_ERROR); // Mipmapping fails if glGetError is not here
glBindTexture(GL_TEXTURE_2D, 0);
Why on earth is this only working when a glGetError (which, as you can see with this assert, is ALWAYS returning GL_NO_ERROR) function is called after the glGenerateMimap? Why does it have anything to do with it?
I'm currently using a GeForce GTX 670 with the latest GeForce 340.52 driver
Edit: A couple of images might help
With glGetError():
Without glGetError():
Referring to Is iOS glGenerateMipmap synchronous, or is it possibly asynchronous?, it seems glGenerateMipmaps works asynchronously. My project uses shared contexts to create shaders, textures and meshes (sorry if I didn't mention this, I didn't think it would matter).
The thing is, whenever the texture generation finished the "textures generated" flag was risen and the shared context would get destroyed, it seems the last glGenerateMipmap was therefore not getting flushed through the pipeline. The call to glGetError needs to flush the operations from the pipeline to see whether there's been any error to report, and this is exactly why it was making everything work flawlessly.
So, in other words, if you're doing something on a separate, shared context, you need to explicitly call glFinish before killing that thread, or some operations will be left undone.
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
Does glTexParamter act on all textures globally or only the texture that is currently bound.
For example, if I call this at the texture load:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
And this on another texture load:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
When I bind the first texture will it just use the last value I set (GL_CLAMP) or will it use the values originally set when the texture was bound?
From the OpenGL FAQ:
21.070 How do texture objects work?
Texture objects store texture maps and their associated texture parameter state. They allow switching between textures with a single call to glBindTexture().
(...)
The following functions affect and store state in texture objects: glTexImage*(), glTexSubImage*(), glCopyTexImage*(), glCopyTexSubImage*(), glTexParameter*(), and glPrioritizeTextures(). Since the GLU routines for building mipmap pyramids ultimately call glTexImage*(), they also affect texture object state.Noticeably absent from this list are glTexEnv*() and glTexGen*(); they do not store state in texture objects.
Ergo, glTexParameter* affects only the bound texture.