How to access corners of a texel

I have a texel (rectangle) and I need to access its 4 corners.

vec2 offset = vec2(1,1)/vec2(texWidth, texHeight)
texture2D (texSource, texCoord + 0.5 * offset * ???? ) 

what should I fill here to get both top 2 and bottom 2 corners.?
I am not looking for nearby texels as in bilinear filtering, I am looking for corners of current texel.

[QUOTE=deeps8us;1282340]I have a texel (rectangle) and I need to access its 4 corners.

vec2 offset = vec2(1,1)/vec2(texWidth, texHeight)
texture2D (texSource, texCoord + 0.5 * offset * ???? ) 

what should I fill here to get both top 2 and bottom 2 corners.?
[/QUOTE]
What does texcoord represent? Some arbitrary location within the texel in question? If so:


ivec2 size = textureSize(texSource, level); // "level" is the mipmap level in question
vec2 origin = floor(texCoord * size);
vec2 topLeft = origin / size;
vec2 topRight = (origin + vec2(1,0)) / size;
vec2 botLeft  = (origin + vec2(0,1)) / size;
vec2 botRight = (origin + vec2(1,1)) / size;

Note that sampling at a texel corner will yield unpredictable results for GL_NEAREST filtering. For GL_LINEAR, it will return the average value of the four texels sharing that corner.

Also, should probably be sampling using textureLod(), given that you need to choose a specific mipmap level in order for “texel corners” to be meaningful.

GClements : Huge thanks for your detailed answer which answered a lot of my questions.

I have some more questions on your comment.

  1. I am trying to find convoluted value of a texel by sampling at its 4 corners.
    I have original approach where I calculated convolved value using gaussian-blur. For performance optimization I am using bilinear filtering by sampling 4 corners of texel.
    My expectation was that sampling at 4 corners around a texel should give same weightage as gaussian-blur
    1 2 1
    2 4 2
    1 2 1

But you have mentioned that "For GL_LINEAR, it will return the average value of the four texels sharing that corner. ". So will it actually give
similar convoluted results as 3x3 gaussian-blur.?

  1. I don’t have textureSize function (‘textureSize’ : no matching overloaded function found : I ma using GL ES 2.0)
    Can I replace that with :
    vec2 size = vec2(1,1)/vec2(offsetx,offsety) where offsetx = 1/width
    offsety = 1/height
vec2 size = vec2(1,1)/vec2(offsetx,offsety);
vec2 origin = floor(vTextureCoord * size);
vec2 topLeft = origin / size;
vec2 topRight = (origin + vec2(1,0)) / size;
vec2 botLeft  = (origin + vec2(0,1)) / size;
vec2 botRight = (origin + vec2(1,1)) / size;						
vec4 p00 = texture2D(sTexture, topLeft);
vec4 p02 = texture2D(sTexture, topRight);
vec4 p20 = texture2D(sTexture, botLeft);
vec4 p22 = texture2D(sTexture, botRight);
vec4 pconv = 0.25*(p00 + p02 + p20 + p22);

Sampling at the four corners and averaging the four results will give the above kernel divided by 16, i.e. the total weight will be one.

textureSize() returns the size of a specific mipmap level of a specific texture. So you can just use


vec2 size = vec2(width,height)

if you have the texture size (more precisely, the size of the mipmap level) in variables. Or just pass in the size as a uniform vec2.

When comparing against the convoluted value got through Gaussian-Blur, this differs greatly. I am missing something here. Texture mapping used is GL_LINEAR.

I have no idea what you’re comparing it to.

Is the alternative sampling the texels at their centres (or using GL_NEAREST) so that the original values are being used?

Are you trying to generate a filtered copy of a texture? Or are you trying to achieve the same result as if you had first generated a blurred texture then sampled it using bilinear filtering? Or as if you had rendered using bilinear filtering then blurred the result as a post-process effect? Or … what?

Also, is the alpha channel significant? If it is, you typically need to use pre-multiplied alpha to get the correct result.

I have an original implementation where I calculate convoltued value of a 3x3 block using Gaussian-Blur algorithm. That uses GL_NEAREST as texture mapping.
For optimization, I thought of replacing 3x3 Gaussian Blur with sampling on 4 corners of texel (as that is also having same weightage). Here I used GL_LINEAR.

Expectation was that the results I get from these 2 approaches should not vary by a wide range. But I got a huge difference.
I tried changing the first texture mapping also to GL_LINEAR and compared. That also gave difference. (Difference in R, G and B component values between 2 approaches upto 5 was acceptable.)
I got about 45 in some cases.

Alpha channel is not significant. It is made 0.0

Well, there’s some aspect of it which isn’t being mentioned. With GL_LINEAR filtering, sampling at each of the four corners corresponds to kernels of


1 1 0    0 1 1    0 0 0    0 0 0
1 1 0    0 1 1    1 1 0    0 1 1
0 0 0    0 0 0    1 1 0    0 1 1

with a divisor of 4.

Averaging the results (i.e. adding and dividing by 4) gives a kernel of


1 2 1
2 4 2
1 2 1

with a divisor of 16.

So if that doesn’t give the same result as a direct approach (i.e. sampling at the centre of each pixel in the 3x3 block and averaging with those weights), then something else is different between the two cases.

How can I ensure that I am sampling from texel center itself and when I try to access a corner, it is indeed a corner.?
Also if I am correctly sampling from texel center, will GL_LINEAR and GL_NEAREST give same result when using a direct Gaussian blur 3x3 convolution.?

Sampling from the centre isn’t necessary if you are using GL_NEAREST.

You’re sampling from a corner if texcoordsize is an integer, and from the centre if texcoordsize-0.5 is an integer.

Yes.

Thankyou GClements. Since I get different results on GL_NEAREST and GL_LINEAR, I guess I am not sampling from texel center. Thus my sampling of corners might have gone wrong. How can I find texel center and then sample its corners.

Thankyou GClements. Since I get different results on GL_NEAREST and GL_LINEAR, I guess I am not sampling from texel center. Thus my sampling of corners might have gone wrong. How can I find exact texel center and then sample its corners.

The code I posted doesn’t require that texCoord be the centre of the texel.

Multiplying by the size converts normalised texture coordinates (in the range 0…1) to un-normalised coordinates (in the range 0…width or 0…height), floor() then discards the fractional part, returning the un-normalised coordinates of the texel’s origin. Dividing by the size converts back to normalised coordinates.

You can calculate the centre similarly, but using round() instead of floor().

But If texCoord isn’t the centre of a texel, that suggests that you aren’t simply generating a 1:1 filtered copy of the texture. If you’re performing the filtering as part of the process of rendering transformed primitives, the effect will (or should) be the same as using a pre-filtered texture with GL_NEAREST filtering (i.e. you’re calculating the value of a single pixel from the filtered texture and using that).

Thank you GClements and sorry for the repeated questions, still not able to get same results from sampling corners and 3x3 gaussian blur.
I am using a mediaplayer application which uses GL_EXTERNAL_TEXTURE_OES. So this does not have any mipmaps. So I am suspecting
that since I dont have 1 to 1 mapping with mipmaps and texel corners doesnt make sense.?