UV texture mapping with perspective correct interpolation
- by Twodordan
I am working on a software rasterizer for educational purposes and I am having issues with the texturing.
The problem is, only one face of the cube gets correctly textured. The rest are stretched edges:
You can see the running program online here.
I have used cartesian coordinates, and all I do is interpolate the uv values along the scanlines.
The general formula I use for interpolating the uv coordinates is pretty much the one I use for the z-buffering interpolation and looks like this (in this case for horizontal scanlines):
u_Slope = (right.u - left.u) / (triangleRight_x - triangleLeft_x);
v_Slope = (right.v - left.v) / (triangleRight_x - triangleLeft_x);
//[...]
new_u = left.u + ((currentX_onScanLine - triangleLeft_x) * u_Slope);
new_v = left.v + ((currentX_onScanLine - triangleLeft_x) * v_Slope);
Then, when I add each point to the pixel buffer, I restore z and uv:
z = (1/z);
uv.u = Math.round(uv.u * z *100);//*100 because my texture is 100x100px
uv.v = Math.round(uv.v * z *100);
Then I turn the u v indexes into one index in order to fetch the correct pixel from the image data (which is a 1 dimensional px array):
var index = texture.width * uv.u + uv.v;
//and the rest is unimportant imagedata[index].RGBA bla bla
The interpolation formula is correct considering the consistency of the texture (including the straight stripes).
However, I seem to get quite a lot of 0 values for either u or v. Which is probably why I only get one face right.
Furthermore, why is the texture flipped horizontally? (the "1" is flipped)
I must get some sleep now, but before I get into further dissecting of every single value to see what goes wrong, Can someone more experienced guess why might this be happening, just by looking at the cube?
"I have no idea what I'm doing" (it's my first time implementing a rasterizer). Did I miss an important stage?
Thanks for any insight.
PS: My UV values are as follows:
{ u:0, v:0 },
{ u:0, v:0.5 },
{ u:0.5, v:0.5 },
{ u:0.5, v:0 },
{ u:0, v:0 },
{ u:0, v:0.5 },
{ u:0.5, v:0.5 },
{ u:0.5, v:0 }