RE: bilinear filtering from sample point (not center of pixel)?

"Matt Franklin" <[email protected]> Wed, 17 May 2006 11:54:28 -0800
Newsgroups gmane.games.devel.opengl
Organization Fat City Network Services, San Diego, California
Message-ID <[email protected]>
Damn, I knew I'd forget some crucial information!

I'm using GL_TEXTURE_RECTANGLE_NV, since we need to render to an R32F
target, for which we're using GL_FLOAT_R32_NV.

Your e-mail got me to go back and look closer at the formats and what
they support, so I could lay them out in this e-mail.  Turns out, that's
the problem.  Dave Dixon here pulled out the NVIDIA GPU Programming
Guide and confirmed the issue: I'm attempting to sample from an R32F,
which does not support bilinear filtering on the 6800.

I apologize for the confusion.  It appears the solution is
straightforward: either implement some filtering in the shader, or blit
the source texture to 16-bit ARGB.  Since in my case I'll be using blend
functionality further along in the pipeline-- which is only supported
with 16-bit ARGB-- the loss of precision is unimportant, though the
extra texture memory is a drawback.

-----Original Message-----
Pat Brown (OpenGL)
Sent: Tuesday, May 16, 2006 8:09 PM
To: Multiple recipients of list OPENGL-GAMEDEV-L

Matt,

Your shader isn't doing anything close to what you think it's doing.

You are adding +/- 0.5 to the (s,t) texture coordinates.  

For TEXTURE_2D, this does not move your sample point by half a pixel.
It moves it by half a TEXTURE.  

For 2D textures, texture coordinates of (0,0) means the lower left
corner of the texture; (1,1) means the upper right corner of the
texture.  (0.5, 0.5) is smack dab in the middle of your texture.

Let's say you have a pixel whose texture coordinate is at (0,0).  You
will take four samples at (+/-0.5, +/-0.5).  If you are using the REPEAT
wrap modes, all four of these samples will end up in exactly the same
location -- half way across your texture from where it "should" be.  

If your pixel and texture coordinates are 1:1 (say a 64x64 texture with
a 64x64-pixel square), your sample points are all smack dab on the
center of a texel, so LINEAR filtering will be weighted 100% on the
texel you do end up picking.  So it looks like you're point sampling
(you're not).

If your texture is 64x64, try adding +/- 1/128 instead.  I think that
will work much better for you.

FWIW, many OGL vendors support an extension called
ARB_texture_rectangle, where textures are addressed in (0,0) - (w,h)
coordinates instead of (0,0) - (1,1).  Rectangle textures have a bunch
of limitations (e.g, no mipmapping, not all wrap modes supported,
etc...), however.  Using rectangle textures, adding +/-0.5 would do what
you wanted.

Hope this helps.

Pat

-----Original Message-----
Matt Franklin
Sent: Tuesday, May 16, 2006 6:19 PM
To: Multiple recipients of list OPENGL-GAMEDEV-L

This is a rather long post.  First, my question in brief: is there a way
to get GLSL's texture sample to return an interpolated value from the
specified texture coordinate, and NOT from the center of the destination
pixel?



I'm attempting to port a simple box filter from DirextX+HLSL to
OpenGL+GLSL.  In the HLSL version, I sample four points: plus or minus
.5 from the center of the texel, along x and y.  By sampling at the
corners of the texel, this allows me to exploit bilinear filtering to
essentially get four samples per sample.  I then average the four points
together, and bingo-- box filter suitable for blurring.  (I've enclosed
the shader at the end of this e-mail, in case that's clearer.)

The same technique is not working for me in GLSL.  I'm using
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN/MAG_FILTER, GL_LINEAR) to
enable bilinear filtering, but it appears I need something further.

Here's the key bit of documentation:

"GL_LINEAR: Returns the weighted average of the four texture elements
that are closest to the center of the pixel being textured."

Well, there's the issue.  My source and destination line up perfectly
(I'm not magnifying or minifying, and they aren't offset).  Since the
center of the pixel being textured lines up perfectly with the texture,
it doesn't sample four texture elements-- it just samples one.  When I
attempt to offset the sample point by .5, .5 (which should put me at the
corner of the texel), it simply point samples the next texel over!

Is there a way to prevent OpenGL/GLSL from "snapping" to the center of
the texel, and instead get it to interpolate appropriately?  Or do I
need to manually implement the interpolation within my shader?  It's not
that writing the full box filter with the 9 samples is difficult, but if
there's a more optimized method that's supported by OpenGL, I'd prefer
to use that.


GLSL SHADER:

The behavior of this shader is to point sample the current texel, the
texel next to it in the positive x direction, the texel next to it in
the positive y direction, and the texel diagonal from it in the positive
x, y.

uniform sampler2D tex0;
void main() {
	const float2 cg_vPixelOffset[4] =
	{
		{-0.5,  -0.5 }, { 0.5,  -0.5 },
		{-0.5,   0.5 }, { 0.5,   0.5 },
	};
	float4 vColor = 0;
	for (int i = 0; i < 4; i++)
	{
		vColor += texture2D(tex0,
gl_TexCoord[0].st+cg_vPixelOffset[i]);
	}
	gl_FragColor = vColor * (1.0f / 4.0f);
}

----- 
FAQ and OpenGL Resources at:
  http://www.geocities.com/SiliconValley/Hills/9956/OpenGL

-- 
Author: Matt Franklin
  INET: [email protected]

Fat City Hosting, San Diego, California -- http://www.fatcity.com
---------------------------------------------------------------------
To REMOVE yourself from this mailing list, send an E-Mail message
to: [email protected] (note EXACT spelling of 'ListGuru') and in
the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
(or the name of mailing list you want to be removed from).  You may
also send the HELP command for other information (like subscribing).
------------------------------------------------------------------------
-----------
This email message is for the sole use of the intended recipient(s) and
may contain
confidential information.  Any unauthorized review, use, disclosure or
distribution
is prohibited.  If you are not the intended recipient, please contact
the sender by
reply email and destroy all copies of the original message.
------------------------------------------------------------------------
-----------

----- 
FAQ and OpenGL Resources at:
  http://www.geocities.com/SiliconValley/Hills/9956/OpenGL

-- 
Author: Pat Brown \(OpenGL\)
  INET: [email protected]

Fat City Hosting, San Diego, California -- http://www.fatcity.com
---------------------------------------------------------------------
To REMOVE yourself from this mailing list, send an E-Mail message
to: [email protected] (note EXACT spelling of 'ListGuru') and in
the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
(or the name of mailing list you want to be removed from).  You may
also send the HELP command for other information (like subscribing).

----- 
FAQ and OpenGL Resources at:
  http://www.geocities.com/SiliconValley/Hills/9956/OpenGL

-- 
Author: Matt Franklin
  INET: [email protected]

Fat City Hosting, San Diego, California -- http://www.fatcity.com
---------------------------------------------------------------------
To REMOVE yourself from this mailing list, send an E-Mail message
to: [email protected] (note EXACT spelling of 'ListGuru') and in
the message BODY, include a line containing: UNSUB OPENGL-GAMEDEV-L
(or the name of mailing list you want to be removed from).  You may
also send the HELP command for other information (like subscribing).