Texture mapping in software rasterizer

This topic is 3013 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

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.

1. 1
2. 2
3. 3
4. 4
Rutin
17
5. 5

• 11
• 27
• 12
• 12
• 11
• Forum Statistics

• Total Topics
631407
• Total Posts
2999914
×