PDA

View Full Version : Texture Array Seam



LogicalError
08-11-2009, 10:01 AM
I was experimenting with texture-arrays and i got a weird seam between the texture-array pages i was rendering.
Basically i'm rendering a square polygon with texture coordinates ranging from 0,0 to 4,4.
The idea was to use the integral part of the coordinates to calculate the index of the texture-array and the fractional part for the texture-array page.

If i use this in my glsl:


gl_FragColor = texture2DArray(tex, vec3(fract(TexCoord), 0));

I get a seam:
http://lh3.ggpht.com/_QB2O0HdIQjQ/SoGOnads9dI/AAAAAAAAAGs/Fe4CQg48L7U/s720/with_seam.jpg

Yet if i remove the fract:


gl_FragColor = texture2DArray(tex, vec3(TexCoord, 0));

And use GL_REPEAT wrapping, the seam dissappears:
http://lh4.ggpht.com/_QB2O0HdIQjQ/SoGOnTltUMI/AAAAAAAAAGo/_JYihv_Qwbo/s720/without_seam.jpg

This is the first time i used texture-arrays...
Am i missing something?
Why would that seam appear?
Wouldn't GL_REPEAT basically be doing the same thing under the hood?

Fract is just the first step in what i'm planning to do (messing around with virtual texture stuff), so i can't use the GL_REPEAT thing.

Edit: Nvidia hardware btw. (just in case it's a driver bug.)

Jan
08-11-2009, 10:13 AM
Hardware handles the cases for 0 and 1 texcoords specially (afaik).

So, at the coordinate 1 (u or v, doesn't matter) it is something different, then if it were coordinate 0.

However, with your "fract" you turn EVERY whole number into a 0 coordinate.

So for one fragment the coordinate is 0.999 and for the one next to it, it is 0.0, where it usually is 1.0. I assume this messes up the texture-lookup (plus derivatives etc.).

Might be difficult / expensive to fix this.

Jan.

Jackis
08-11-2009, 10:23 AM
Jan is right, that is because of derivative constructions and mip-mapping. I can't say nothing on special handling for 1 and zero, but when you call "fract", you always have two neighbor fragments with say (0.999) and (1) coordinates. So gradient construction breakes for that texels.
What you can do - is explicitly suplying gradients for texel fetch. With your approach it is quite simple - just call ddx() and ddy() for texCoord before fraction.

LogicalError
08-11-2009, 10:23 AM
But if that's the case, why does it still work properly with GL_REPEAT then?
I didn't show that in the screenshots or the shader code, but if i use -different- texture-array indices it still works with GL_REPEAT..
I also tried adding a value to the coordinates after using fract, but that didn't move the seam oddly enough

Jackis
08-11-2009, 10:24 AM
It works with GL_REPEAT not because of GL_REPEAT, but because you removed fractioning from your shader code, and derivatives are constant across whole triangle.

LogicalError
08-11-2009, 10:31 AM
Ah, OK!
So this is how i understand it:

With GL_REPEAT and no fract, one sample coordinate is maybe 2.9 and the one next to it 3.0.. a difference of 0.1 ... the derivatives are constant, and AFTER that GL_REPEAT does the 'fract' internally...

But if i use fract, the sample coordinate is fract(2.9) == 0.9 and the one next to it fract(3.0) == 0.0.. a difference of 0.9 ... the derivatives are no longer constant, and THAT causes the seam..

Jackis
08-11-2009, 10:33 AM
The code you should use is something like this:

textureGrad2DArray(tex, vec3(fract(TexCoord.xy), TexCoord.z), dFdx(TexCoord.xy), dFdy(TexCoord.xy))

Jan
08-11-2009, 10:38 AM
Ah, OK!
So this is how i understand it:

With GL_REPEAT and no fract, one sample coordinate is maybe 2.9 and the one next to it 3.0.. a difference of 0.1 ... the derivatives are constant, and AFTER that GL_REPEAT does the 'fract' internally...

But if i use fract, the sample coordinate is fract(2.9) == 0.9 and the one next to it fract(3.0) == 0.0.. a difference of 0.9 ... the derivatives are no longer constant, and THAT causes the seam..


Yep, that nails it.

LogicalError
08-11-2009, 10:39 AM
The code you should use is something like this:

textureGrad2DArray(tex, vec3(fract(TexCoord.xy), TexCoord.z), dFdx(TexCoord.xy), dFdy(TexCoord.xy))

Awesome! I got it to work now, thanks!
Just for the record, in case someone finds this post when having a similar problem, it was just "textureGrad" not "textureGrad2DArray".

LangFox
08-11-2009, 01:42 PM
Nice tip!

Xmas
08-12-2009, 02:16 AM
Just using REPEAT is more efficient, though.

Ilian Dinev
08-12-2009, 05:55 AM
Yet, it can be useful to have different wrapping modes per layer :)