#144861 - TwentySeven - Thu Nov 08, 2007 12:24 pm
Hi,
I've been messing around wondering why my meshes were coming out on the DS Hardware with texture seams visible when my OpenGL renderer was fine..
I managed to fix it, so I thought I'd share what might be common knowledge, but it wasnt immediately obvious to me and nor could I find a mention of it on the web anywhere( but I might be just dumb ).
"S/T texture coordinates need the S to be offset in the positive direction by half a texel."
So if you were using a 64x64 texture on a quad and wanted it fitted perfectly between: (bad ascii art of UV's on a quad)
0,0 -- 1,0
|
0,1 -- 1,1
and then converted to 4/10 fixed point format for a 64x64 texture:
0,0 ---- 1024,0
|
0,1024--1024,1024
you'd have to actually pass in:
16,0 ---- 1040, 0
|
16,1024 -- 1040,1024
to get it to render equivilantly to openGL
The "16" figure is what half a texel at 64x64 works out to be.
#144866 - simonjhall - Thu Nov 08, 2007 2:10 pm
You got any pictures/photos of what it looks like with/without this offset?
Just curious, since my textures are like, (off the top of my head!)
Code: |
0,0 ---- 1008,0
|
0,1008--1008,1008
(note: 1008 not 1024) |
...and I see no seams...
_________________
Big thanks to everyone who donated for Quake2
#144883 - TwentySeven - Thu Nov 08, 2007 11:02 pm
I'll take some today.
*edit* Heres what I did.
http://27.blackrayne.net/dsquirk/texture.png
This is the texture I'm using to test. You might have to blow it up to tell but it has a row of coloured texels along each edge, and different 1 texel colours in each corner.
I'm rendering that on a pair of triangles arranged as a triangle strip.
Texture is loaded via:
Code: |
glTexImage2D(0, 0, GL_RGB, TEXTURE_SIZE_64 , TEXTURE_SIZE_64, 0, TEXGEN_OFF|GL_TEXTURE_WRAP_S|GL_TEXTURE_WRAP_T, (byte*)point);
|
http://27.blackrayne.net/dsquirk/standard.png
And here's what it looks like, with the UV's of each vertex printed out.
http://27.blackrayne.net/dsquirk/halfpixel.png
And here it is with the half texel nudge on the "S" axis.
Last edited by TwentySeven on Thu Nov 08, 2007 11:45 pm; edited 1 time in total
#144891 - TwentySeven - Thu Nov 08, 2007 11:44 pm
Quote: |
Code: | 0,0 ---- 1008,0
|
0,1008--1008,1008
(note: 1008 not 1024) |
|
Yeah thats exactly what we started off with from our exporter too
* TextureWidth-1
* TextureHeight-1
to get something 0-63
Here's a screenshot of how that looks on my end, for completeness.
http://27.blackrayne.net/dsquirk/0to1008.png
Now I'm really starting to wonder if theres something really wrong with my 3d initialization code after all this.. maybe its just that I'm using triangle strips?
The behavior is the same under both no$gba and the real hardware.
#144899 - nce - Fri Nov 09, 2007 12:46 am
TwentySeven wrote: |
Yeah thats exactly what we started off with from our exporter too
* TextureWidth-1
* TextureHeight-1
|
I usually always use the same uv coordinate system ( meaning I consider all texture to be 128 * 128 ) and use the texture matrix to scale it correctly depending of the real texture size.
I do this because when I'm doing a scene I prefer to export my mesh once, and if I change my texture ( often shrink it because I realise that I use a too big texture for the distance ) I just have to rebuild my texture pack. and not reexport everything :)
_________________
-jerome-
#144905 - TwentySeven - Fri Nov 09, 2007 1:02 am
You bring up an interesting point about texture matrixes. I don't initialize or use one at all.. I just pass in the UV's directly to the hardware in their proper 32bit 10|4 10|4 packing.
Its funny, i didn't even consider using a texture matrix to use "normalized" UV's.. Maybe using a matrix fixes the issue?
#151325 - TwentySeven - Sat Feb 23, 2008 12:07 pm
The DS just has unusual texel sampling rules.
It seems to be the hardware rasterizer is sampling from the center top of pixels, which is unlike d3d or opengl.
It's not because I wasn't using a texture matrix. However a texture matrix does offer a convenient way to correct for this so you can just store your UV's without fudging around with them.
So to start with, I base everything around uv's for a 64x64 texture. It was suggested on these forums to use a larger range like 256x256 for more precision.
Code: |
u32 uv64[] =
{
TEXTURE_PACK(inttot16(0),inttot16(0)),
TEXTURE_PACK(inttot16(64),inttot16(0)),
TEXTURE_PACK(inttot16(64),inttot16(64)),
TEXTURE_PACK(inttot16(0),inttot16(64)),
};
|
uv setup for a 64x64 textured quad - note its 0-64 not 0-63
because normalized Uvs go from 0.0f-1.0f, not 0 to 0.984375 ;)
Texture initialization looks like:
Code: |
glTexImage2D(0, 0, GL_RGBA, TEXTURE_SIZE_64 , TEXTURE_SIZE_64, 0, TEXGEN_TEXCOORD|GL_TEXTURE_WRAP_S, (byte*)data);
|
GL_TEXTURE_WRAP_S is required or you will be unable to sample from column 63 at all >_<
GL_TEXTURE_WRAP_T can introduce 1 pixel sparklies in row 0 sampled from row 63, on the real hardware.
The setup code for the texture matrixes with the sampling correction factored in looks like:
Setup to render a 64x64 texture
Code: |
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
MATRIX_TRANSLATE = (32<<12);//half a texel on S at 0-64 uv range
MATRIX_TRANSLATE = 0;
MATRIX_TRANSLATE = 0;
|
Set up to render a 128x128 texture, same UV's
Code: |
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
//Translate goes first, woops
MATRIX_TRANSLATE = (32<<12); //nudge for 0-64 range
MATRIX_TRANSLATE = 0;
MATRIX_TRANSLATE = 0;
MATRIX_SCALE = (int)(2*(1<<12));
MATRIX_SCALE = (int)(2*(1<<12));
MATRIX_SCALE = (int)(2*(1<<12));
|
Last edited by TwentySeven on Wed Feb 27, 2008 9:13 am; edited 1 time in total
#151328 - silent_code - Sat Feb 23, 2008 3:01 pm
sorry, but isn't it: texel 0 = 0.0 = (fxpt)0, texel 63 = width - 1 = 1.0 = (fxpt) 1008 (just like simon's [btw: greetings and thanks for ? a.k.a. Q2 ;^p !] setup)... because normally in a 64 texel wide texture map, the 64th texel would be texel 0 with texture wrapping enabled. that shouldn't change with normalized uvs at all. at least i don't get the logic behind such a thing.
or is it really like that on the nds (i can't remeber, i got such results in my tests, at all)? i mean, your results *sure* look odd...
ps: i guess, you all are familiar with openGL's texture mapping offset, right? like, you have to use a small offset for perspective projected geometry to make things really right, as well as another offset, which differs from the former, for othogonal projected geometry. otherwise it's especially hard to get correct results in text drawing etc.
that might just be the nds' flavor of the same thing. i really have to get back to nds dev soon to check that out! ;^D
#151346 - simonjhall - Sat Feb 23, 2008 10:49 pm
I think a lot of things with DS 3D are hit and miss. I really really wish I had the proper hardware docs so I could just read them and "oh, right THAT's what's going on!" but there's no way I'd wanna be a pro DS developer.
Back on topic :-)
I guess if you get seams or whatever with whatever you're doing, just wiggle the inputs until you get exactly what you want. Once you've done that, invent some understanding of how you think the internals actually work!
Thinking about it, maybe it does make sense to define your co-ords as going from 0-64, not to 0-63 cos as you say 0.0-1.0 is what you'd do with other hardware- and software-render solutions.
Kusma, what say you?
Btw anyone know what's the deal with those texturing artifacts you get where the sides of texels seem to wiggle on the triangles they're drawn onto? (not so much when on quads)
Kinda looks like the hardware doesn't step correctly in s/z and t/z...
edit: @ silent_code, ta mate! I was like "I gave you €? I donated you money? Ahhh!" :-D
_________________
Big thanks to everyone who donated for Quake2
#151363 - silent_code - Sun Feb 24, 2008 4:17 pm
@simon... ha, ha, ha... :^D i didn't even THINK about that! i just saw (i think it was tepples) someone making that refernece to the euro-sign and thought it was funny... ;^D
well, i'll have a look at that topic today.