Bilineal interpolation of textures in software rendering
category: general [glöplog]
I'm working right now in software rendering with textures. I want to do something the same way the hardware does it, and I have a question about it.
Suppose I have a 512x512 pixels texture. Without bilineal interpolation, I would say that the range to access it would be [0, 512) or [0.0f, 1.0f). First, do hardware do it that way? I mean, above or equal to 0, and below 512.
Then, with bilineal interpolation, how is it done? The same? Does the position (0.0f, 0.0f) is the full value of color of the texel in (0,0)?
Suppose I have a 512x512 pixels texture. Without bilineal interpolation, I would say that the range to access it would be [0, 512) or [0.0f, 1.0f). First, do hardware do it that way? I mean, above or equal to 0, and below 512.
Then, with bilineal interpolation, how is it done? The same? Does the position (0.0f, 0.0f) is the full value of color of the texel in (0,0)?
Not sure if I get your question...
You normally take the four surrounding texels with bilinear interpolation.
So U = 2.4 and V = 5.6 [2.4,5.6] will use texels at [2,5],[3,5],[2,6] and [3,6].
You normally take the four surrounding texels with bilinear interpolation.
So U = 2.4 and V = 5.6 [2.4,5.6] will use texels at [2,5],[3,5],[2,6] and [3,6].
No. Sampling the texture at (0,0) gives a 25% mix of the texels at (-1,0), (0,0), (-1,-1) and (0,-1). How to address those texels is a question of wrap mode.
And then you lineary interpolate between the first two and the last two, and then between the result of those two interpolations.
Kusma, huh?
Rob: the "No"-part was meant to answer texel's question "Does the position (0.0f, 0.0f) is the full value of color of the texel in (0,0)?"
yep (0.5/512, 0.5/512) does. (texels are sampled at their center, texel)
Quote:
No. Sampling the texture at (0,0) gives a 25% mix of the texels at (-1,0), (0,0), (-1,-1) and (0,-1). How to address those texels is a question of wrap mode.
The half texel offset thing is particular to DX9 though, DX10 got rid of that nonsense.
oh, shit, talking about texels with nick texel is fucking confusing.
Anyway, thanks, I've the info I wanted. :)
Anyway, thanks, I've the info I wanted. :)
<quote>The half texel offset thing is particular to DX9 though, DX10 got rid of that nonsense.</quote>
What are those wrap modes? And does dx10 have a different wrap mode by default then?
What are those wrap modes? And does dx10 have a different wrap mode by default then?
keops: Are you sure about that (DX10)? A quick experiment reveals that (0,0) is still bottom left corner of the first texel at my PC in DX10... Or did I completely misunderstand what you meant?
Also: I can't find any mention of it in the documentation...
http://msdn.microsoft.com/en-us/library/cc308049(VS.85).aspx
http://msdn.microsoft.com/en-us/library/bb205073(VS.85).aspx
"[...]
Mapping Texels to Pixels in Direct3D 10
In Direct3D 9, texel centers and pixel centers were a half unit apart (see Directly Mapping Texels to Pixels (Direct3D 9)). In Direct3D 10, texel centers are already at half-units [...]"
http://msdn.microsoft.com/en-us/library/bb205073(VS.85).aspx
"[...]
Mapping Texels to Pixels in Direct3D 10
In Direct3D 9, texel centers and pixel centers were a half unit apart (see Directly Mapping Texels to Pixels (Direct3D 9)). In Direct3D 10, texel centers are already at half-units [...]"
Yeah, but that's the PIXEL centers that has been redefined, not the texel centers.
Don't get me wrong, the mapping-thing was quite annoying, and I'm glad it's solved ;)
Just noticed that I wrote half texel instead of half pixel in my former post, I understand why you were not following me. Blame Texel and his nick for that typo, I meant pixel of course :D
Thanks!
hint: for sw rendering with bilinear filtering it is really, really useful to demand that textures repeat the first row and column in memory, so you need to compute an adresse only for one of the 4 bilinear samples.
also note that there are two ways to compute adresse: step in texels and do a mod for clamping or clipping (and and shift if you have power of two) or step always in 0..1 as say .16 fixed point and multiply by texture size after clamping to 0..1, especially if you want non power of 2 textures.
also note that there are two ways to compute adresse: step in texels and do a mod for clamping or clipping (and and shift if you have power of two) or step always in 0..1 as say .16 fixed point and multiply by texture size after clamping to 0..1, especially if you want non power of 2 textures.
Thanks shiva. I remember doing things like that, for example, with the same amount of memory, creating a long texture pre-interpolated. a 256x256 to 256x1024 and just interpolating in the x. Only 4 values of interpolation in the y, but use to be enough and very fast.
Also, I remember reordering the textures in 8x8 or 16x16 blocks, for a better cache coherence...
I'm used to code it, but now I want to do it the most similar as possible as hardware/direct X do it, for a little software project I'm working on.
Also, I remember reordering the textures in 8x8 or 16x16 blocks, for a better cache coherence...
I'm used to code it, but now I want to do it the most similar as possible as hardware/direct X do it, for a little software project I'm working on.
speaking of non power of two textures, how should one implement them nowadays on x86? no clamping or clipping.
In the 90s we used 32bit registers for the fractional part and created a small 4 items offset table which was indexed using carry flags from u and v fractinal part overflows (sbb+adc trick).
In the 90s we used 32bit registers for the fractional part and created a small 4 items offset table which was indexed using carry flags from u and v fractinal part overflows (sbb+adc trick).
This thread is turning into a pub quiz for demoscene legends. ;)
I'll take polygone techniques for $200, Alex!
I appreciate the recent increase in serious coding questions.
I'll add:
That why in OpenGL and 3D apis there is preferences about how texture mapping should react on texture borders, with things like:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP );
or
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT );
... also defined in opengl there is the possibility to define a "blank border" to textures, and you can specify the width of that texture border.
... plus, I guess a perfect bilinear mapping should place the exact color of the texel at the "center" of the square that appear in "nearest" mode, which can be just done in software by adding -0.5 pixel.
That why in OpenGL and 3D apis there is preferences about how texture mapping should react on texture borders, with things like:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP );
or
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT );
... also defined in opengl there is the possibility to define a "blank border" to textures, and you can specify the width of that texture border.
... plus, I guess a perfect bilinear mapping should place the exact color of the texel at the "center" of the square that appear in "nearest" mode, which can be just done in software by adding -0.5 pixel.
coincidentally I was yesterday cheating the bilinear interpolation hardware of GPUs to get smoother (and twice derivable) texture mapping: article (sorry for the quality of the text) The trick is cheap and saved my ass in some LUT based algorithms...