# Perspective correct barycentric coordinates

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

## Recommended Posts

As title, I'm trying to do perspective correct texturing in a software renderer. So far I have non-perspective correct texturing by looping over the bounding box of a triangle, calculating the barycentric coords, then either rejecting the pixel or using the coords to do texturing. Simple (and slow) but works, and I'm trying not to worry *too* much about performance right now.

In particular, I'm trying to implement this as described by Erik Rufelt here, that is, some magic barycentric coord formula that I can't quite find/grasp that generates perspective correct interpolants, instead of going the long way and correcting them manually for every value to be interpolated.

Maxest's thesis lists pseudo code for this, but I can't figure out what the distance() pseudo instruction does, nor how it relates to my existing barycentric coord calculation, as it appears to be using a completely different approach.

So far, I have this:
 public void rasteriseTriangle(Vector3f ndc0, Colour4f c0, Vector2f uv0, Vector3f ndc1, Colour4f c1, Vector2f uv1, Vector3f ndc2, Colour4f c2, Vector2f uv2) { Vector2f p0 = ndcToScreen(ndc0); Vector2f p1 = ndcToScreen(ndc1); Vector2f p2 = ndcToScreen(ndc2); // First find screen rect (clamped to screen bounds) final int screenXMin = Math.max((int)Math.floor( Math.min(Math.min(p0.x, p1.x), p2.x) ), 0); final int screenYMin = Math.max((int)Math.floor( Math.min(Math.min(p0.y, p1.y), p2.y) ), 0); final int screenXMax = Math.min((int)Math.ceil( Math.max(Math.max(p0.x, p1.x), p2.x) ), backbuffer.getWidth()-1); final int screenYMax = Math.min((int)Math.ceil( Math.max(Math.max(p0.y, p1.y), p2.y) ), backbuffer.getHeight()-1); // Iterate final float detT = (p1.y - p2.y) * (p0.x - p2.x) + (p2.x - p1.x) * (p0.y - p2.y); // If detT == 0, then triangle is degenerate, so skip if (detT != 0.0f) { // Loop over screen bounds for (int y=screenYMin; y<=screenYMax; y++) { for (int x=screenXMin; x<=screenXMax; x++) { // l1 = (y2 - y3)(x - x3) + (x3 - x2)(y - y3) / detT // l2 = (y3 - y1)(x - x3) + (x1 - x3)(y - y3) / detT // l3 = 1 - l2 - l1 final float l1 = ( (p1.y - p2.y) * ((float)x - p2.x) + (p2.x - p1.x) * ((float)y - p2.y) ) / detT; final float l2 = ( (p2.y - p0.y) * ((float)x - p2.x) + (p0.x - p2.x) * ((float)y - p2.y) ) / detT; final float l3 = 1.0f - l2 - l1; // If barycentric coords are all in the range [0, 1] then we lie in the triangle // - we add a small epsilon on the compare with zero check to fill the edges correctly // - we don't actually have to compare againct one because with the equation above none // all of the coords sum to one final float epsilon = -0.000000059604645f; if (l1 >= epsilon // && l1 <= 1.0f && l2 >= epsilon //&& l2 <= 1.0f && l3 >= epsilon //&& l3 <= 1.0f ) { // Within triangle! // Find depth by lerping vertex depths final float z = ndc0.z * l1 + ndc1.z * l2 + ndc2.z * l3; // Depth buffer just has raw depth values // Test depth buffer final int pixelLoc = x + y * backbuffer.getWidth(); if (z <= depthBuffer[pixelLoc]) // TODO: Also test for z<1 for far plane clipping { // Write depth buffer depthBuffer[pixelLoc] = z; // Lerp vertex colours final float r = c0.r * l1 + c1.r * l2 + c2.r * l3; final float g = c0.g * l1 + c1.g * l2 + c2.g * l3; final float b = c0.b * l1 + c1.b * l2 + c2.b * l3; final float a = c0.a * l1 + c1.a * l2 + c2.a * l3; // Lerp texture coords final float u = uv0.x * l1 + uv1.x * l2 + uv2.x * l3; final float v = uv0.y * l1 + uv1.y * l2 + uv2.y * l3; // Sample texture Colour4f textureColour = testTexture.sample(u, v); final int red = (int)((r * 255.0f) * (textureColour.r)); final int green = (int)((g * 255.0f) * (textureColour.g)); final int blue = (int)((b * 255.0f) * (textureColour.b)); final int alpha = (int)((a * 255.0f) * (textureColour.a)); final int argb = packRgba(red, green, blue, alpha); int[] pixels=((DataBufferInt)(backbuffer.getRaster().getDataBuffer())).getData(); pixels[pixelLoc] = argb; } } } } } }

Any pointers as to what I'm conceptually not getting would be helpful. Thanks.

##### Share on other sites
Oh, I also found this presentation, which superficially makes more sense, but again the actual formulas escape me, probably because it seems to introduce new variables / letters without actually defining them. >_< If anyone can give me some hints as to how to understand the 'edge vectors' in it then that would be helpful. Thanks.

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 11
• 15
• 21
• 26
• 11