View Full Version : Tex Coord for Middle of a Texture Rectangle

09-27-2002, 05:28 AM
If I have a 256x256 GL_Texture_Rectangle_NV

Is the middle at 127.5, 127.5 or 128, 128

I think the coords run from 0 - 256.0 which would make the exact center 128,128

The center of the first pixel would be 0.5, 0.5 and the center of the last 255.5, 255.5

Is this correct ?

09-27-2002, 05:57 AM
The first half of your texture coordinates is 0,1,2,...,127 and the second half of your texture coordinates is 128,129,130,...,255 (there is no pixel 256, 0-255 is 256 pixels)

So the exact middle of your texture would be 127.5 If I'm not mistaken, texture rectanges want integers for texture coordinates, so whether you round up or down is up to you, if you pass 127.5 in, I'm going to assume the driver will round down. My question is, is there something wrong with GL_TEXTURE_2D?


09-27-2002, 07:57 AM
If there is an even number of pixels how can the middle of the texture be in the middle of a pixel?

Even if the 255th pixel is the 255th, it is still one pixel wide, making 256 pixels.

The middle is obviously exactly between the 128th and 129th pixels. If we restrict ourselves to integers then is no middle pixel.

If we are using floating point then it is just .5, which would map to the left edge of the 129th pixel or the right edge of the 128th pixel.

I am not up enough on the opengl spec to know off the top of my head what .5 maps to if you are using NEAREST filtering.

[This message has been edited by Nakoruru (edited 09-27-2002).]

09-28-2002, 08:59 AM

I think you're wrong.

If we assume wrapping for a moment (as a thought experiment) then 0.0 is the "same" position as 256.0; both locations lie between the first and the last pixel. Thus, 128.0 would like exactly between two halves of the texture, where each half contains 128 pixels.

This is easier to think about if you think of pixels as squares separated by a grid. The grid lines are numbered with whole integers, and the center of each square (pixel) is between two integers, and thus should correspond to a .5 coordinate.

09-28-2002, 09:47 AM
Right. The exact center of a 1x1 texture rectangle is (0.5, 0.5). The exact center of a 2x2 texture rectangle is (1,1). The exact center of a 256x256 texture rectangle is (128,128).

In general it's (w/2.0, h/2.0).

Thanks -

09-28-2002, 08:24 PM
Ok, I think I know where my train of thought got derailed. I thought that the texture coordinate was for the actual pixel (I guess meaning the center of the pixel), but it's actually the boundary edges of the pixels, right? not the inside of the pixel.


09-29-2002, 02:19 PM
Texels values *are* at the center of the texel.

09-29-2002, 05:21 PM
There is no middle to a 256x256 sized image, or any even numbered size image for that matter. You're either on one side or the other.

So, does OpenGL round up or down? If you feed in 0.5f, does it map to 127 or 128 of a 256x256 size texture, assuming the range is 0 to 255?

[This message has been edited by WhatEver (edited 09-29-2002).]

09-29-2002, 05:22 PM
Never mind, I just saw your post cass. It rounds up accoording to you.

09-29-2002, 05:36 PM
x = u * width - 1
y = v * width - 1

So with a 256x256 image you get this:

x = 127 = 0.5f * 256 - 1
y = 127 = 0.5f * 256 - 1

That means it naturally rounds to 127, and not 128. Interesting. So 0.5f maps to the lesser side.

Don't mind me, I'm just bored http://www.opengl.org/discussion_boards/ubb/smile.gif.

09-29-2002, 05:48 PM

With filtering, 0.5 maps to the average of the 4 centermost pixels. Perhaps your question is: when you're in nearest mode filtering, which pixel does 0.5,0.5 map to?

I know that if you draw a rectangle from 0,0 to 256,256 when the modelview is set to be == viewport coordinates, and map that to a 256x256 texture, then the texel http://www.opengl.org/discussion_boards/ubb/tongue.gifixel correlation will be 1:1. This leads to the surprising revelation that OpenGL, when rasterizing that triangle, actually will NOT rasterize a pixel at 0,0, but will rasterize a pixel at (0.5,0.5) in window coordinates.

At least, that's the best I can come up with in how to explain how this works.

09-29-2002, 06:03 PM
I see. Yes, I would be talking about nearest mode. I was having a flashback to the non-filtered mode days http://www.opengl.org/discussion_boards/ubb/smile.gif.

It should also be assumed that in my example the texture is clamped.

Here's something I never understood. Why is your texture shifted over a bit when you choose to repeat the texture? If you have a texture that can be tiled, there's no reason for it to be shifted...none that I can see anyway.

[This message has been edited by WhatEver (edited 09-29-2002).]

09-29-2002, 07:21 PM
Changing the WRAP mode shouldn't change the filtered texels - except where they wrap.

If we forget multisample, pixels are sampled at their center. That is where "coverage" is determined, and the location inside a polygon where values are interpolated.

That point where a polygon is sampled is used to produce a texture coordinate. That texture coordinate is used to look into a texture with cell-centered samples.

For me, it's easiest to think of these things as independent.

Thanks -

09-30-2002, 12:44 PM
If I draw two quads side by side with a texture covering the whole quad and with a clamped texture, you don't see a seem...but if the texture is set to repeat, you see that the textures are shifted down and to the right by one pixel causeing a seem. The far right column of pixels will be on the left side of the quad...and the bottom row of pixels will be at the top of the quad.

It's not really that big a deal, it just seams strange that the pixels would be shifted down and to the right by one.

09-30-2002, 12:48 PM
Wait wait wait wait!

You mean if I wasn't filtering I wouldn't get that seem? So I can assume that the seem is caused by the filtering of surounding pixels...in the case of reapeating, the left column would be filtered along with the right column and visevesa.

Revelation baby!

I love understanding http://www.opengl.org/discussion_boards/ubb/smile.gif.

09-30-2002, 01:59 PM
Originally posted by WhatEver:

Revelation baby!

I love understanding http://www.opengl.org/discussion_boards/ubb/smile.gif.

Cass is my Guru http://www.opengl.org/discussion_boards/ubb/smile.gif

09-30-2002, 04:57 PM
I feel the need to explain OpenGL texture filtering and sampling every so often. The spec doesn't explain it well -- I rewrote this for 1.4, but it didn't make it in.

One easy way to think about texture sampling is to assume that your texture map is a piece of graph paper. (0,0) is the lower left corner of the lower left texel. (1,1) is the upper right corner of the same texture. If your texture is m by n, (m,n) is the upper right corner of the last texel. The center of the texel is always (X.5, Y.5).

GL_NEAREST is basically "give me the color of the cell containing the sample point". GL_LINEAR is basically "draw a 1-pixel square around the sample point and compute an average color".

If you draw an aligned texture rectangle with window coordinates (0,0) through (m,n), your texture coordinates should cover the same range. Each pixel is sampled at the center with window coordinates (x.5, y.5). The corresponding texture coordinates are the same, so you hit the middle of the texel.

It shouldn't matter if you use NEAREST or LINEAR (the 1-pixel square for LINEAR falls right on the texture map). In practice, you might get small rounding errors.

Clamp modes deal with what happens when your coordinates make you fall off.

First, we fix the sample point. For REPEAT and MIRRORED_REPEAT, the sample point bounces around in the obvious manner. For CLAMP, the sample point is clamped to the extent of the texture map. If it falls off, it goes straight to the edge. For now, CLAMP_TO_EDGE and CLAMP_TO_BORDER do nothing.

Next, we look at the sample filter, in particular what happens if we fall off the edge of the map. For 2D (or rectangle) textures, normal filters will sample 1-4 texels. For REPEAT, if the texel you sample is off one edge, you wrap around to the other edge. For CLAMP_TO_EDGE, your samples go back to the edge texture. MIRRORED_REPEAT works like CLAMP_TO_EDGE (seams between textures have the same texel repeated twice). For CLAMP and CLAMP_TO_BORDER, if you fall of the edge, you get either the border texel (if it's in the image) or the constant border color.

CLAMP is the least intuitive mode. If you fall of the edge of a texture map, you start getting the border color blended in. But you will never more than 50% border (75% in corners) since your sample point is always clamped to the edge, producing a 50/50 filter.

This is pretty useless. If you see seams in a tiled texture, it's probably because you used CLAMP and are seeing the border color. (To be sure, change the border color and your seams should change color.)

As I mentioned above, if you use a LINEAR filter with a 1:1 mapping of pixel to texels, you should get the same results as NEAREST. Except rounding errors may leave you off by a little bit, and you end up seeing a little bit of border. Annoying! Use CLAMP_TO_EDGE instead.

Anyone still awake? If so, hope this helps.

[This message has been edited by pbrown (edited 09-30-2002).]

09-30-2002, 07:59 PM
I'm awake! Thanks for the description, Pat!

One comment: for GL_LINEAR, would you describe the "1-pixel square" as a square that connects texel centers of the 4 nearest samples? Just making sure what I think you mean by the 1-pixel square...

Thanks -

10-01-2002, 12:05 PM
I think he means that there a square that's exactly as large as a texel, and which is centered on the texture coordinate being fetched. The contributions of the four texels this square may intersect are weighted in relation to how much area of each texel the texel-sized square covers.

Once you've gotten used to thinking like this, you can think of MIP mapping as a texel-unit-sized cube in the texture stack (sort of :-) and anisotropic filtering as a texel-unit-sized cube that's been stretched by the partial derivatives of the texture coordinates and thus is no longer cube-shaped.

10-01-2002, 02:29 PM

Since you're talking about a box that is centered on the texture coordinate being fetched... for this case - with linear filtering, I usually think of the reconstruction filter as a tent /\ that is two units wide. The area under the tent is 1.0.

How does what I'm describing jibe with the one unit wide box?

Thanks -

10-01-2002, 05:51 PM
jwatte accurately described what I was suggesting.

The "correct" model is to project the pixel to texture space and compute a weighted average of the texels in the footprint.

Normal GL_LINEAR effectively assumes that the footprint is a 1-texel by 1-texel axis-aligned square centered around the sample point.

Normal mipmapping tries picks LODs where the real footprint is "closest" to this one-texel square.

Anisotropic filtering does a more complicated (oblong) sample pattern that more closely approximates the true footprint.

You can obviously think about this in other ways -- that's just my mental model.

10-01-2002, 07:34 PM
My explanation in the previous post might not have been real clear. A "graph paper" example of what I'm talking about might be helpful.

Let's say our (u,v) coordinate is (1,1). Then the 1-texel square centered around the sample point goes from (0.5, 0.5) to (1.5, 1.5). 1/4 of the square lies in each of the (0,0), (1,0), (0,1), and (1,1) cells, so you blend them together equally.

If the (u,v) coordinate is (0.75, 0.75), the square goes from (0.25,0.25) to (1.25, 1.25). More than half of that square (0.75^2) lies inside (0,0). Only 1/16th of the square (0.25^2) lies inside (1,1). So you blend them together with weights that favor (0,0).

This set up explains which texels are sampled and how the filter weights work in an intuitive way (at least intuitive to me).

But it's probably completely identical to the tent filter model discussed by Cass without the requirement of knowing what a tent filter is. :-)

10-02-2002, 05:01 AM
Ok, thanks Pat and jwatte.

I get it now. http://www.opengl.org/discussion_boards/ubb/smile.gif


10-02-2002, 05:08 AM
A more deep understanding can be achieved by reading the source code of mesa. http://cvs.sourceforge.net/cgi-bin/viewc....viewcvs-markup (http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/mesa3d/Mesa/src/swrast/s_texture.c?rev=

Notice the macro

and function

[This message has been edited by inet (edited 10-02-2002).]

10-02-2002, 05:09 AM
Maybe someone should write a paper on this, describing all the details.

I have a related question:
With cubemaps, why does everyone ( including me ) set the wrap parameter for the R coordinate ? After the face is selected, isn't it just S and T that are used ?

10-02-2002, 08:23 AM

Right - it is meaningless to set the wrap mode for R with cube mapping. I have been guilty of this in the past as well. http://www.opengl.org/discussion_boards/ubb/smile.gif


10-02-2002, 10:13 AM
So what happens if you use LINEAR and REPEAT at coordinate 0.0 and 1.0?

I guess it doesn't sample from the opposing edge, and this is why BORDER is used.

Does anyone think that border is really needed in glTexImage? Why not just have GL_CLAMP behave like CLMAP_TO_EDGE and have artists deal with the textures to get the right effect in things like skyboxes.


10-02-2002, 05:11 PM
Originally posted by V-man:
So what happens if you use LINEAR and REPEAT at coordinate 0.0 and 1.0?

I guess it doesn't sample from the opposing edge, and this is why BORDER is used.

Does anyone think that border is really needed in glTexImage? Why not just have GL_CLAMP behave like CLMAP_TO_EDGE and have artists deal with the textures to get the right effect in things like skyboxes.


If by "at coordinate 0.0 and 1.0" you are referring to the (s,t,r) coordinates -- not scaled by the texture size -- then LINEAR/REPEAT does wrap around to the other side. You'll get 50% left edge, 50% right edge if you're dealing with the s coordinate.

Texture borders can "automagically" patch together pieces of a larger texture. With PixelStore, it's trivial to make small textures from large images. You still have to slice your geometry apart to get the right results.

You can achieve much of the same functionality by breaking your textures up into overlapping pieces. You do need more pieces without borders.

As a naive example, you might split up an 8x8 texture into 9 overlapping 4x4 slices. Along one diagonal, the slices would go from (0,0)-(3,3), (2,2)-(5,5), and (4,4)-(7,7). You still slice up the geometry and texture, but the border is effectively inside the image.

10-02-2002, 09:31 PM
Why not just have GL_CLAMP behave like CLMAP_TO_EDGE and have artists deal with the textures to get the right effect in things like skyboxes.

Because that's how GL was originally designed. That is something that can only be fixed by GL2.0.

10-03-2002, 05:34 PM
>>>Texture borders can "automagically" patch together pieces of a larger texture. With PixelStore, it's trivial to make small textures from large images. You still have to slice your geometry apart to get the right results.<<<<

Meaning that when you need to use a texture larger than the maximum width supported by hardware, you are forced to break it up and also break up your geometry and rework your texture borders.

This could still be done by the application (game).

I'm looking forward to GL 2, but the next version was suggested as 1.5 for doing the arb_fragment thing.