Enable conformant OpenGL texture clamp behaviour

I spent about 15 minutes looking through the OpenGL spec trying to find an answer to this.

If I have bilinear or trilinear filtering turned on and I provide texture coordinates that specify a subsection of a larger texture, will OpenGL ever sample outside of the texture coordinates?

I always thought the answer to this was yes (ie. OpenGL doesn’t clamp to the triangle’s texture gamut or do centroid sampling on subpixel fragments).

The OpenGL spec seems to be silent on this issue… or did I miss something?

I’ve noticed Nvidia’s control panel has an option “Enable conformant OpenGL texture clamp behaviour”, but doesn’t provide enough of a description what this does for it to be useful to a programmer, except to state its related to texture clamping. Does anyone know exactly what this does?

(Disclaimer : I did not tested/verified everything reported here)

Short answer : use always GL_CLAMP_TO_EDGE (instead of GL_CLAMP) for GL_TEXTURE_WRAP_* parameters of glTexParameter so that there will never be sampling outside the texture.

Long answer : if Nvida’s “Enable conformant texture clamp” is off, it basically turns every GL_CLAMP to _GL_CLAMP_TO_EDGE, because so many apps/demos/games misused GL_CLAMP.

To me, GL_CLAMP is made to be used with texture borders : useful when several textured quads (a texture for each) are made to be adjacent in a 2D sprite background.

<speculative part>
In this case, with GL_CLAMP_TO_EDGE, you need :

  • duplicating the rightmost texels column of left texture, to the left of right tex.

With GL_CLAMP, you need :

  • using the same texture border for right side of left texture and left side of right texture.
    </speculative part>

Any details on this, from someone having heavily used GL_CLAMP/…TO_EDGE ?

Edit: fixed meaning for “Enable conformant”

Originally posted by Stephen_H:
I always thought the answer to this was yes (ie. OpenGL doesn’t clamp to the triangle’s texture gamut or do centroid sampling on subpixel fragments).
The texture coordinate clamp is done when you sample, so your texture coordinate fed into the shader could be a bit off but you still get a sample from the texture that’s entirely outside the border (with GL_CLAMP_TO_EDGE). Centroid sampling on the other hand fixes the texture coordinate fed into the shader when the pixel center is outside of the primitive.

Originally posted by ZbuffeR:
this Nvidia “Enable conformant texture clamp” basically turns every GL_CLAMP to _GL_CLAMP_TO_EDGE, because so many apps/demos/games misused GL_CLAMP.
Should be the other way around, as that behavior is not conformant with the OpenGL spec.

If I have bilinear or trilinear filtering turned on and I provide texture coordinates that specify a subsection of a larger texture, will OpenGL ever sample outside of the texture coordinates?
Yes, it is possible for GL to sample outside of the specific texture coordinate range you specify. Filtering needs 2x2 blocks of pixels, and those at the edge will need samples from across the edge.

If you don’t want this, you need to make sure that you’re specifying texture coordinates that leaves a pixel or a half-pixel outside the textured region.

My understanding of the issue is that the wording for the behavior of GL_CLAMP used to be such that doing the same thing as GL_CLAMP_TO_EDGE was acceptable. With OpenGL 1.2, the wording for GL_CLAMP was fixed to specify a mixed sampling of both the texture and the border, and the mode GL_CLAMP_TO_EDGE was added.

Of course, this meant that some existing applications may have already assumed the texture addressing mode went one particular way and didn’t look right with the “new” behavior.

Originally posted by Humus:
[quote]Originally posted by ZbuffeR:
this Nvidia “Enable conformant texture clamp” basically turns every GL_CLAMP to _GL_CLAMP_TO_EDGE, because so many apps/demos/games misused GL_CLAMP.
Should be the other way around, as that behavior is not conformant with the OpenGL spec.
[/QUOTE]You are right, that is what I meant, I fixed my post.

>> If you don’t want this, you need to make sure that you’re specifying texture coordinates that leaves a pixel or a half-pixel outside the textured region.
You meant a half-texel, right ?

Thanks for the replies.

If I understand correctly:

GL_CLAMP - clamps to [0,1], so that you’re texture filter can fall off the edge of the texture (but only if its a texture with borders)

GL_CLAMP_TO_EDGE - clamps to [0 + (1 texel), 1 - (1 texel)], so that the texture filter can never fall off the edge of the texture

So if you’re not using textures with borders, both GL_CLAMP and GL_CLAMP_TO_EDGE should give the same behaviour. A disadvantage of using GL_CLAMP_TO_EDGE though is that is can modify your texture coordinates slightly which you might not want if you’re using them to specify some attribute for a pixel shader (eg. a GPGPU application where its important it doesn’t ‘cook’ the texcoords for you).

Also if you have say a black triangle in the middle of a white texture, and you are selecting exactly that black triangle with texture coordinates to texture an actual triangle, you will get bleeding of the white at the edges (are there any ways to force OpenGL to use centroid sampling? (I seem to remember something in the multisample ext, I’ll have to look at that again))

No. No clamping mode modifies texture coordinates; it only changes what is fetched from the texture when the texel being fetched would lie outside the actual texture image.

GL_CLAMP says that the fetched texel is the border color. GL_CLAMP_TO_EDGE says that it is the color of the nearest texel.

The problem with nVidia’s implementation arose because GL_CLAMP_TO_EDGE didn’t exist in GL for quite some time (GL 1.2 introduced it). This, coupled with the fact that nobody wants GL_CLAMP behavior (it is rarely useful, especially compared to GL_CLAMP_TO_EDGE), and what do you get? Well, you get a lot of GL developers complaining to nVidia that they’re getting black lines at the edges of their textures, and that it is a hardware problem. Since GL provided no GL_CLAMP_TO_EDGE at the time, they had no real choice but to make GL_CLAMP behave like GL_CLAMP_TO_EDGE.

Once done, it could not be undone without breaking lots of early GL games. Though only recently has nVidia exposed the ability to activate conformant behavior in their implementation.

Texture borders are simple and very neat ! GL_CLAMP makes really sense with that. Plus it works even with mipmapping, whereas offsetting texcoords does not.
Why isn’t it used more ? Lack of hardware support ? All post-geforce2 cards seem to support it though.

I plan to do some webpages with screenshots to illustrate all this, it looks really needed.

About the black triangle texture example, I fail to see a connection with texture clamping ? To me, with lower mipmaps, you will always end up with white bleeding.

Forgive my lack of knowledge, but what is exactly centroid sampling ?
I searched for it, only to find ATI marketing cra^H^H^H vague informations. In english, does ‘centroid’ means ‘barycentric’ ?

Originally posted by Korval:

The problem with nVidia’s implementation arose because GL_CLAMP_TO_EDGE didn’t exist in GL for quite some time (GL 1.2 introduced it). This, coupled with the fact that nobody wants GL_CLAMP behavior (it is rarely useful, especially compared to GL_CLAMP_TO_EDGE), and what do you get? Well, you get a lot of GL developers complaining to nVidia that they’re getting black lines at the edges of their textures, and that it is a hardware problem. Since GL provided no GL_CLAMP_TO_EDGE at the time, they had no real choice but to make GL_CLAMP behave like GL_CLAMP_TO_EDGE.

I’m sorry, but that’s just simply not correct.

First, both SGIS_texture_edge_clamp and EXT_texture_edge_clamp predate TNT. Other implementors (even in the consumer market) supported these extensions back then.

Second, even after OpenGL 1.2, TNT through GeForce2 silently “fell back” to GL_CLAMP_TO_EDGE when asked to GL_CLAMP. No developer could complain to NVIDIA about black lines in their textures, because TNT through GeForce2 wouldn’t give them black (or more commonly tinted grey) lines with GL_CLAMP.

Third, early GeForce 3 drivers finally had conformant GL_CLAMP behavior. So for the first time NVIDIA faced the same complaints from developers that most other implementors had heard for years - your “GL_CLAMP” is broken because I’m seeing texture borders in my cubemaps/skyboxes/edges of textures. I don’t blame developers, they developed and tested on non-conformant hardware, and often filed bug reports against conformant hardware.

“Compatibility” won over conformance, so later drivers added the still misunderstood conformance checkbox.

Finally, GL did provide (through widely implemented extensions) GL_CLAMP_TO_EDGE_SGIS and GL_CLAMP_TO_EDGE_EXT, so there really was a correct choice to make.

(Oh, in fairness, Nvidia wasn’t the first implementor to get this stuff wrong.)

Anyhow, water under the bridge.

-mr. bill

Originally posted by ZbuffeR:

Forgive my lack of knowledge, but what is exactly centroid sampling ?
I searched for it, only to find ATI marketing cra^H^H^H vague informations. In english, does ‘centroid’ means ‘barycentric’ ?

No, it’s obsolescent slang, unit of currency on Tatooine, it means one-hundredth of a droid. (from centidroid). Banned by the Republic and replaced with “credits.” Beware, local traders only accept “Wuipiupi”, which is an underground untaxed currency.

[insert silly smiley face]

See http://mathworld.wolfram.com/GeometricCentroid.html

In this context, if the polygon being rasterized doesn’t cover the center of a pixel, then it is shaded at the centroid, rather than at the center.

-mr. bill