# Texture mapping in software rasterizer

## Recommended Posts

I am having an issue in my software renderer where if I draw a triangle or a quad that isn't parallel to the viewport, the texture will skew rather than do a perspective correct transformation. As the image below shows, along the boundaries of the triangles in the quads, the texture skews; if the quad was a parallelogram, the texture would fit without distortion. But, as it is a trapezoid, the two triangles have mismatched skewed images. The image is looking inside of a cube with the nearest face culled; the quad farthest away is a scaled down version of what the texture would look like. http://i871.photobucket.com/albums/ab274/Ectara/comp.png The question I'm wondering is, is there any sort of transformation I could be applying to the texture coordinates to gain the correct information to rotate the texture coordinates or something? Bear in mind, I do have a modelview matrix, but using it doesn't guarantee that the triangle won't just be drawn skew to the viewport plane to begin with.

##### Share on other sites
you are right,its not perspective correct interpolated. lookup for perspective vorrect texture interpolation on google, there are plenty of tutorials, like those from chris hecker.

##### Share on other sites
Thanks Krypt0n. I tried looking it up, and implementing the concepts found several times. But, all the formulas I could find use the so-called "poor man's projection"( x/z, y/z, 1/z). Mine uses a projection matrix and a homogenous divide by w. I can't seem to figure out how to implement this with my setup.

##### Share on other sites
You have to interpolate (u/w, v/w, 1/w) and homogenize it by dividing through 1/w at the end.

##### Share on other sites
Quote:
 Original post by EctaraThanks Krypt0n. I tried looking it up, and implementing the concepts found several times. But, all the formulas I could find use the so-called "poor man's projection"( x/z, y/z, 1/z). Mine uses a projection matrix and a homogenous divide by w. I can't seem to figure out how to implement this with my setup.

I've asked a similar question some time ago
http://www.gamedev.net/community/forums/topic.asp?topic_id=564019

there you have some links and explanation how to interpolate UVs (but ginkgo's explanation is kinda the short version :) ).

maybe you could tell me how you interpolate z in your none-poor-man's rasterizer.
It's working for me with just linear interpolation, but I was sure it cannot be interpolated linearly :/

##### Share on other sites
For getting perspective correct you need to divide by a linearly interpolated value for each pixel.

  // Setup values needed for each scanline  float uw = ..., vw = ..., w = ...  float duw = ..., dvw = ..., dw = ...  // Plot each pixel in scanline  for x in scanline {     float u = uw / w     fluat v = vw / w     plot(x, y, texture(u, v))     uw += duw     vw += dvw     w += dw  }

Where w are the same w you use for position. You should be able to calculate the rest of the values.

[Edited by - mzeo77 on March 18, 2010 6:29:11 AM]

##### Share on other sites
As for my projection function:
void E_renderProject(vector3 world, vector3 screen){	vector4 v;		/*These transform functions multiply {arg2[0],arg2[1],arg2[2],1.0f} by the matrix pointed to by the first argument, and the result is copied to the third argument*/	E_renderTransformVector34(E_globalRenderContext.raster.model, world, v);	/* Point is not visible, don't bother. */	if(!E_renderClipFrustumPoint(v)){		screen[0] = screen[1] = screen[2] = -1;		return;	}	/*Likewise, but with {arg2[0],arg2[1],arg2[2],arg2[3]}*/	E_renderTransformVector4(E_globalRenderContext.raster.projection, v, v);		/* Don't divide by zero, but don't raise an error; this could occur normally, I'd suppose. Set it to zero to give a clue that it failed.*/	if(!v[3]){		_E_vectorClear(screen);		return;	}		/*Divide X, Y, and Z by W*/	_E_vectorDivideScalar(v,v[3],v);	v[0] = v[0] * 0.5f + 0.5f;	v[1] = v[1] * 0.5f + 0.5f;	v[2] = v[2] * 0.5f + 0.5f;		v[0] *= E_globalRenderContext.display->image->width;	v[1] *= E_globalRenderContext.display->image->height;	v[1] = E_globalRenderContext.display->image->height - v[1];		if(v[2] > 1){		v[0] = -v[0];		v[1] = -v[1];	}		/* In this line, the w coordinate is discarded. Only using 3D for now. */	_E_vectorCopy(screen,v);}

Then, to interpolate Z later on, I lerp 1/Z. Note that the W is discarded. Should I be keeping the extra dimension for each vertex?

##### Share on other sites
Thanks gingko, ProfL, and mzeo77 for the advice. Modified a projection function and a couple structures to use the w coordinate, and interpolated using homogeneity that way. It is now evident that the w coordinate should not be discarded after projection, and the formulae in Wikipedia and such are unusable for my purposes. I got it working, and here's a before and after image: http://i871.photobucket.com/albums/ab274/Ectara/comp.png. For the interpolation, I used pretty much the same algorithm from Wikipedia, except with 'w' replacing 'z', and several optimizations.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628377
• Total Posts
2982325

• 10
• 9
• 14
• 24
• 11