Texture-mapped triangles - warped halves

Started by
9 comments, last by iMalc 19 years, 3 months ago
I have no idea how you texture map a triangle "properly", as it were, just a method I dreamt up which seems to work pretty well and fairly quickly, apart from when one half is "short" - the triangle is drawn in two halves, firstly from the top y to the middle y and then the middle y to the bottom y, filling in scanlines as it goes. Anyway. If the difference in 'y's is smallish, the texture is distorted. I fill each scanline by specifying the (u,v) of the left x coordinate and the (u,v) of the right x coordinate and interpolating as I go along. The (u,v) coordinates are calculated through interpolating as I go through the y values, so I'm guessing that it's down to the prescision. Any ideas how I can better fill triangles?

[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

Advertisement
i suppose it has something to do with rounding floating point vertex coords to int screenspace coords. when you snap your vertices to the grid of your screen, you should also displace your UV coords. however, this might cause negative UV coords. i must say i dont have a clue how this dilemma is commonly solved.
Quote:Original post by Eelco
i suppose it has something to do with rounding floating point vertex coords to int screenspace coords. when you snap your vertices to the grid of your screen, you should also displace your UV coords. however, this might cause negative UV coords. i must say i dont have a clue how this dilemma is commonly solved.

It might also be due to the very crap way I calculate scanline boundaries - if the edge is taller than it is wide I use a hacked-about Bresenham, and that is fine and very fast. However, if the line is shorter-than-wide then Bresenham would calculate multiple x coordinates for each y which is wasteful and innacurate for what it needs to do - so I do some messy jiggery-pokey with doubles and rounding to ints. The visual effect is that some triangles have flashing horizontal lines half way down from time to time - which isn't much good.

[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

perhaps a screenshot would help to picture the problem better?
are you doing a perspective or affine interpolation for texcoords?
if you're not using perspective interpolation then your "distortion" might very well be the affine distortion... hard to tell without a picture...

btw, if you're not using perspective interpolation, just interpolate 1/z, u/z and v/z instead of interpolating u and v, then for each pixel (or each group of 4, 8, 16 pixels) on a scanline, get the correct texcoords back by dividing the interpolated 1/u and 1/v values with the interpolated 1/z value. that's it :)

and about the "or each group of 4, 8, 16 pixels", that's just a cheap way to get a performance closer to affine mapping, without requiring one div per pixel. every 4, 8, or 16 (32 will really look bad), compute the new u and v, and lerp to the next values, 4, 8, or 16, etc.. pixels ahead.
I may be incorrect, but I thought that the bresenham line algorithm contained a branch that basically asks 'is deltaX > deltaY?' and then behaves properly in either case. Perhaps I'm thinking of another algorithm - the one I'm talking about is in abrash's black book, so you might want to look into getting that (or just the graphics half since the first half of the black book is outdated now).
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Quote:Original post by Extrarius
I may be incorrect, but I thought that the bresenham line algorithm contained a branch that basically asks 'is deltaX > deltaY?' and then behaves properly in either case. Perhaps I'm thinking of another algorithm - the one I'm talking about is in abrash's black book, so you might want to look into getting that (or just the graphics half since the first half of the black book is outdated now).


Yes, you are correct - which is why I'm using a simplified version of Bresenham's line algorithm. You see, if the dX < dY, I use this...
## # <- every loop I get the next y value, #    so it's nice and fast.  #  #


However, it's a line drawing algorithm, so if I have a line where dY < dX:
##  ##     <- in this case we only calculate one new y    ##      coordinate every 2 loops - not so.      ##


You see? I get multiple scanline ends for a triangle like that.

As far as affine vs perspective - I'm not familiar with either, but know the symptoms of affine - and my problem is not so pronounced. I can't get a screenshot, but here's a sketch from paint:



The bottom half is fine - the top is distorted. It's really a problem when the top half is very short - then there is clearly a row of pixels that just isn't right.

[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

I'm pretty sure this is a problem with the interpolation. To get correct texture mapping you have to use perspective correct interpolation rather than straight linear interpolation.

[edit]this may help you out, googling for Perspective Correct Texture mapping or texture mapping interpolation or other similar terms should give you lots more info[/edit]
Note: None of the shots below show the original problem. When a triangle has one side very closely aligned to horizontal there is very heavy distortion.

I had seen the GDNet article on texture mapped triangles, and the image in it led me to believe that my method was not straight affine mapping. I don't know.
Here's a shot that shows off the worst effect:



The effect is less visible in high-polygon models:





...and stress testing the renderer with high polygon-count models: (~4000 triangles)



The few holes in the models (under "Polly's" chin, on the wings of "Maledict") are caused by pretty brutual backface culling and near-plane culling. I need to fix those!

[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

Chris Hecker's Perspective Texture Mapping could be of great use. You might also consider using a different method for rasterization: Advanced Rasterization.
from your screenshots, your problem definitely is affine vs perspective interpolation.

try doing what I said, interpolate 1/u, 1/v and 1/z instead of u and v, then at each pixel, pultiply the interpolated 1/u and 1/v value by the interpolated 1/z value.

and you should go have a look at the link COD1F1ED posted... :)

This topic is closed to new replies.

Advertisement