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; \
} \
}
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)
