Texture Mapping - Perspective Problems

Started by
2 comments, last by kylejones 15 years, 4 months ago
So I'm trying to write a texture mapper and having some difficulties. First I'm going to give a description of what I've tried so far then get to some code. I started with a simple rasterizer with this kind of basic algorithm: 1. Find top vertex in polygon 2. Get next vertices on left & right side by going counter clockwise & clockwise 3. Calculate # of scan lines, dxdy, and prestep the current x values for the segments on each side 4. Starting at the top vertex, step through each scan line 5. Take the left and right interpolated positions, draw a line in between 6. Increment positions by dxdy for each side 7. When the scan lines for a side reach 0, calculate that side again 8. If no more scan lines for that side, return So then my next step was to do affine texture mapping. So I took the same code and when calculating each segment I also calculate dudy and dvdy and the current u and v values for each side. Then on each scan line I take the left and right values, divide by the width to get dudx and dvdx. When going across each pixel I then draw texel for u and v and increment by dudx and dvdx. That all works great, no problems there. Next I try perspective texture mapping. After reading a bit I understood I need to do the same for 1/z, u/z and v/z. Doing the same calculations as for u and v in the affine texture mapping, I calculate the delta-y and current values for the inverse of z on each side, then for the delta-x across the span line. At each pixel I use 1/(1/z) for my depth buffer. Seems to be working just fine. Then I ran into problems. I'm trying the same basic thing for the u/z and v/z as I have for 1/z, but I'm getting distorted textures. Looks pretty much the same as affine texture mapping. Texture mapped cubed The relevant code looks something like this:

/* snippet from left segment calc (right portion is identical except names) */
 var dy = pointBottom.y - pointTop.y;
 scanlinesl = ceiling(pointBottom.y) - ceiling(pointTop.y);
 var prestep = ceiling(pointTop.y) - pointTop.y;

 dxdyl = (pointBottom.x - pointTop.x) / dy;
 xl = pointTop.x + prestep * dxdyl;

 dzidyl = ([1] / pointBottom.z - [1] / pointTop.z) / dy;
 zil = [1] / pointTop.z + prestep * dzidyl;

 duzidyl = (texturePointBottom.u / pointBottom.z - texturePointTop.u / pointTop.z) * dyi;
 uzil = texturePointTop.u / pointTop.z + prestep * duzidyl;

 dvzidyl = (texturePointBottom.v / pointBottom.z - texturePointTop.v / pointTop.z) * dyi;
 vzil = texturePointTop.v / pointTop.z + prestep * dvzidyl;


/* snippet from main loop */
while (scanlines--) {
 var x = floor(xr); /* Drawing scan lines from right to left */
 var width = x - floor(xl);

 var zi = zir;
 var uzi = uzir;
 var vzi = vzir;

 var dzidx = (zir - zil) / width;
 var duzidx = (uzir - uzil) / width;
 var dvzidx = (vzir - vzil) / width;

 while (width--) {
  var z = [1] / zi;
  var u = floor(uzi * z);
  var v = floor(vzi * z);

  setPixel(x, y, z, u, v);

  zi -= dzidx;
  uzi -= duzidx;
  vzi -= dvzidx;
 }

 y++;
 xl += dxdyl;
 xr += dxdyr;
 zil += dzidyl;
 zir += dzidyr;
 uzil += duzidyl;
 uzir += duzidyr;
 vzil += dvzidyl;
 vzir += dvzidyr;
 scanlines--;
 scanlinesl--;
 scanlinesr--;
}
if (!scanlinesl) {
 nextSegmentLeft();
}
if (!scanlinesr) {
 nextSegmentRight();
}

I'm hoping that's enough to illustrate where I might be going wrong. Any ideas?
Advertisement
Looking at it closer, it looks as though the z value does have an effect on the texture, but in the opposite direction as I would want (texture shrunken when closer to camera). I think the z values must be wrong, so I have the logic mixed up somewhere along the way from object space to viewing coordinates.
This is a know problem, to solve it you have to use 'perspective correction'. All GPUs do it nowaday. Can't help you with an algorithm, but I think google will help you ;-)

Good luck.

--
Ashaman
Found my bug. Nothing was wrong with the texture interpolation, the z values were getting messed up in my projection transformation.

This topic is closed to new replies.

Advertisement