Problem with GL_TEXTURE_WRAP when using fragment shaders

Started by
4 comments, last by matiasw 14 years, 1 month ago
I'm having problems with the GL_TEXTURE_WRAP parameter on some hardware configurations. I have a fragment shader that samples a texture. On my PC with an NVidia 9500M, it works fine. On a Macbook with an Nvidia 9400M, it doesn't. The symptoms: 1) when using GL_CLAMP_TO_EDGE mode, it works like the specification says on the PC: the edge texel is repeated for texture coordinate values that are out of bounds. On the Macbook, it only repeats edge values when the texture coordinate is out of bounds on one end; on the other, the color repeated is black (the default border color), and not the edge texel color. So it looks like GL_CLAMP_TO_EDGE on the left side of the texture, but GL_CLAMP_TO_BORDER on the right. 2) In a similar vein, the GL_REPEAT mode does not work correctly on the Mac when I sample the texture in the fragment shader, and does on the PC. I have attached some pictures that demonstrate this: wrong.jpg and right.jpg. These are of the same frame, rendered on the two architectures with executables compiled from the same source, so I think that the problem is not entirely in my code. The problem, of course, are the black areas in wrong.jpg. Since these issues seem to be specific to the OpenGL implementation, I'm having a hard time figuring out a way around them. I would appreciate any ideas you might have. Thanks!
Advertisement
Are you setting up the wrap modes after you call glBindTexture?
Something like
glBindTexture
glTexParam

and then create the texture
glTexImage2D

or are you calling glTexParam during your rendering code?

I suggest the former since it is more common.
Also, it is a driver bug no matter which case you use. Do the usual : update drivers, communicate with the apple forum since some experts are over there.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
Quote:Original post by V-man
Are you setting up the wrap modes after you call glBindTexture?
Something like
glBindTexture
glTexParam


Yes, this is what I'm doing, but

Quote:Original post by V-man
and then create the texture
glTexImage2D


Actually, I am working with a plugin architecture where the host application creates the texture and passes the handle to the plugin. I then bind it, store the original texture params, change them, render, and change them back.

Quote:Original post by V-man
or are you calling glTexParam during your rendering code?


Well, the code that gets executed within the plugin per each frame consists of binding the shader, binding the texture & changing the parameters, and rendering the texture to a quad, to be processed by the fragment shader.

Quote:Original post by V-man
Also, it is a driver bug no matter which case you use. Do the usual : update drivers, communicate with the apple forum since some experts are over there.


That's what I was afraid of, but just how can the implementation for the default wrap mode (ie, GL_REPEAT) be so broken?! :(


Anyway, I was wondering if it would be a terrible performance hit (on top of being an ugly hack) to just emulate the wrap modes within the fragment shader..? You know, writing custom code for scaling the texture coordinates to the 0..1 range... :/
Or maybe a less ridiculous workaround exists?

PS: I forgot to mention that the texture is part of an FBO. Could this have something to do with it?

[Edited by - matiasw on February 24, 2010 11:40:48 AM]
Quote:Original post by matiasw
Anyway, I was wondering if it would be a terrible performance hit (on top of being an ugly hack) to just emulate the wrap modes within the fragment shader..? You know, writing custom code for scaling the texture coordinates to the 0..1 range... :/
Or maybe a less ridiculous workaround exists?

PS: I forgot to mention that the texture is part of an FBO. Could this have something to do with it?


FBO doesn't cause a problem.
The wrap mode is easy to emulate with a call to frac() or I think it is called fract(). It would cost one extra GPU cycle.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
Quote:Original post by V-man
The wrap mode is easy to emulate with a call to frac() or I think it is called fract(). It would cost one extra GPU cycle.


Alright, well thanks for all your help! I'll get cracking on a workaround, then.
For anyone else who might stumble upon this issue, here's code to emulate the behavior of the wrap modes in the fragment shader:

GL_CLAMP_TO_EDGE:
xy = clamp(abs(xy), 0.01, 0.99);


GL_REPEAT:
xy = fract(xy);

This topic is closed to new replies.

Advertisement