On Friday 28 January 2005 23:33, Timothy Miller wrote:
> It appears that I've left out a texture clamping mode.  I have the two 
> below, but I've left out simply CLAMP.
> 
>      case CLAMP_TO_EDGE:
>          if (U < 0) U = 0;
>          if (U > Umask) U = Umask;
>          break;
>      case CLAMP_TO_BORDER:
>          if (U < 0 || U > Umask) return border_color;
>          break;
> 
> 
> I honestly can't be sure if I've gotten either of those right either. 
> It's not entirely clear what the spec (p. 169) means when it refers to a 
> "border pixel".  I had assumed that to refer to a separate order color 
> constant, but now, I'm not so sure.  What do coordinates mean when they 
> are outside of the range of the texture?

When the spec refers to a "border pixel", this can mean two things:
- a constant border color
- Texture images can have a one pixel wide border; in this case, the border 
pixel is a pixel from this border.
However, I don't think *any* graphics card out there accelerates textures 
with a border (maybe the hardware that supports arbitrary npot textures 
also supports border). So you can treat it as just referencing a 
per-texture constant color. We'll select a fallback in the driver if the 
applications requests a "real" border texture.

Wrap mode CLAMP is specified to just clamp texture coordinates to [0,1] 
without any further special processing. So when the texture coordinates are 
sufficiently far outside of [0,1], there will always be a 1:1 blending 
between the corresponding edge texel and the border texel.

A good code reference which always turned out to be correct when I compared 
it to the spec during these discussions is Mesa's software renderer, in 
particular src/mesa/swrast/s_texture.c. I've pasted a relevant macro at the 
end of this mail.

cu,
Nicolai

Some quick notes:
- The _EXT modes are not part of core OpenGL, but may be integrated at some 
future time.
- The I0, I1 output are integers in the range [-1, width]. If the output is 
-1 or width, sample the border color instead of the texture image.
- Use frac(U) == U-I0 as the coefficient for linear blending

/*
 * Used to compute texel locations for linear sampling.
 * Input:
 *    wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER
 *    S = texcoord in [0,1]
 *    SIZE = width (or height or depth) of texture
 * Output:
 *    U = texcoord in [0, width]
 *    I0, I1 = two nearest texel indexes
 */
#define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
{         \
   if (wrapMode == GL_REPEAT) {      \
      U = S * SIZE - 0.5F;      \
      if (tObj->_IsPowerOfTwo) {     \
         I0 = IFLOOR(U) & (SIZE - 1);     \
         I1 = (I0 + 1) & (SIZE - 1);     \
      }         \
      else {        \
         I0 = repeat_remainder(IFLOOR(U), SIZE);   \
         I1 = repeat_remainder(I0 + 1, SIZE);    \
      }         \
   }         \
   else if (wrapMode == GL_CLAMP_TO_EDGE) {    \
      if (S <= 0.0F)       \
         U = 0.0F;       \
      else if (S >= 1.0F)      \
         U = (GLfloat) SIZE;      \
      else        \
         U = S * SIZE;       \
      U -= 0.5F;       \
      I0 = IFLOOR(U);       \
      I1 = I0 + 1;       \
      if (I0 < 0)       \
         I0 = 0;       \
      if (I1 >= (GLint) SIZE)      \
         I1 = SIZE - 1;       \
   }         \
   else if (wrapMode == GL_CLAMP_TO_BORDER) {    \
      const GLfloat min = -1.0F / (2.0F * SIZE);   \
      const GLfloat max = 1.0F - min;     \
      if (S <= min)       \
         U = min * SIZE;      \
      else if (S >= max)      \
         U = max * SIZE;      \
      else        \
         U = S * SIZE;       \
      U -= 0.5F;       \
      I0 = IFLOOR(U);       \
      I1 = I0 + 1;       \
   }         \
   else if (wrapMode == GL_MIRRORED_REPEAT) {    \
      const GLint flr = IFLOOR(S);     \
      if (flr & 1)       \
         U = 1.0F - (S - (GLfloat) flr); /* flr is odd */ \
      else        \
         U = S - (GLfloat) flr;  /* flr is even */  \
      U = (U * SIZE) - 0.5F;      \
      I0 = IFLOOR(U);       \
      I1 = I0 + 1;       \
      if (I0 < 0)       \
         I0 = 0;       \
      if (I1 >= (GLint) SIZE)      \
         I1 = SIZE - 1;       \
   }         \
   else if (wrapMode == GL_MIRROR_CLAMP_EXT) {    \
      U = (GLfloat) fabs(S);      \
      if (U >= 1.0F)       \
         U = (GLfloat) SIZE;      \
      else        \
         U *= SIZE;       \
      U -= 0.5F;       \
      I0 = IFLOOR(U);       \
      I1 = I0 + 1;       \
   }         \
   else if (wrapMode == GL_MIRROR_CLAMP_TO_EDGE_EXT) {   \
      U = (GLfloat) fabs(S);      \
      if (U >= 1.0F)       \
         U = (GLfloat) SIZE;      \
      else        \
         U *= SIZE;       \
      U -= 0.5F;       \
      I0 = IFLOOR(U);       \
      I1 = I0 + 1;       \
      if (I0 < 0)       \
         I0 = 0;       \
      if (I1 >= (GLint) SIZE)      \
         I1 = SIZE - 1;       \
   }         \
   else if (wrapMode == GL_MIRROR_CLAMP_TO_BORDER_EXT) {  \
      const GLfloat min = -1.0F / (2.0F * SIZE);   \
      const GLfloat max = 1.0F - min;     \
      U = (GLfloat) fabs(S);      \
      if (U <= min)       \
         U = min * SIZE;      \
      else if (U >= max)      \
         U = max * SIZE;      \
      else        \
         U *= SIZE;       \
      U -= 0.5F;       \
      I0 = IFLOOR(U);       \
      I1 = I0 + 1;       \
   }         \
   else {        \
      ASSERT(wrapMode == GL_CLAMP);     \
      if (S <= 0.0F)       \
         U = 0.0F;       \
      else if (S >= 1.0F)      \
         U = (GLfloat) SIZE;      \
      else        \
         U = S * SIZE;       \
      U -= 0.5F;       \
      I0 = IFLOOR(U);       \
      I1 = I0 + 1;       \
   }         \
}

Attachment: pgp4razCqiqA8.pgp
Description: PGP signature

_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to