0
$\begingroup$

I'm interpolating normals for Phong lighting models. Since I am calculating in the light of each pixel, I'm doing the interpolating after the viewport transform has been applied. So I save a version of the vertices in eye coordinate in order to do barycentric coordinate on them.

I get all these weird negative barycentric coordinates though. For example one is (-14928, 18491, -3562). What am I doing wrong? This very barycentric coordinate I also use for my texture mapping, and since it gets weird big negative result, it broke the index of my texture map.

for (int Y = minY; Y <= maxY; Y++) {
    for (int X = minX; X <= maxX; X++) {
        float lambda1, lambda2, lambda3;
        getBarycentricCoordinate(v1, v2, v3, X, Y, &lambda1, &lambda2, &lambda3);
        if ((0.0f <= lambda1 && 0.0f <= lambda2 && 0.0f <= lambda3)) {
            float zValue = lambda1 * zA + lambda2 * zB + lambda3 * zC;
            if (abs(zValue) < abs(raster.zBuffer[Y * rasterWidth + X])) {// If a point is closer to the eye, which is at (0, 0, 0) then draw. zBuffer check
                float lamb1, lamb2, lamb3;
                getBarycentricCoordinate(eyeCoorV1, eyeCoorV2, eyeCoorV3, X, Y, &lamb1, &lamb2, &lamb3);

                Vector4f incidentPoint = lamb1 * eyeCoorV1 + lamb2 * eyeCoorV2 + lamb3 * eyeCoorV3;
                Vector4f l = lightInEyeCoor - incidentPoint;

                //transforming normals to eye coordinates
                Vector4f normal1 = modelViewMatrix * objects[k].vertexNormal[vn1Index];
                Vector4f normal2 = modelViewMatrix * objects[k].vertexNormal[vn2Index];
                Vector4f normal3 = modelViewMatrix * objects[k].vertexNormal[vn3Index];
                Vector4f normal = lamb1 * normal1 + lamb2 * normal2 + lamb3 * normal3; // lamb1,lamb2 lamb3 are getting weird results

                l.normalize();
                normal.normalize();

                Colorf color = pointLight.LdLs * objects[k].KaKd * fmaxf(l*normal, 0.0f); // add diffuse color
                color = color + ambientLight * objects[k].KaKd; // add ambient color
                Vector4f r = 2 * (normal * l) * normal - l;
                Vector4f v = -incidentPoint; // because eye is at (0, 0, 0) in eye coordinate, view vector is just negative incidentPoint
                r.normalize();
                v.normalize();
                //specular lighting 
                color = color + pointLight.LdLs * objects[k].Ks * powf(fmax(r*v, 0.0f), objects[k].Ks.A);
                raster.pixels[Y * rasterWidth + X] = floatColorToIntColor(color);
                raster.zBuffer[Y * rasterWidth + X] = zValue;
            }
        }
    }
}

Below is the code for my barycentric coordinate

void getBarycentricCoordinate2D(Vector3f & v1, Vector3f & v2, Vector3f & v3, int X, int Y, float * l1, float * l2, float * l3) {
    float denonimator = (float)((v2.y - v3.y) * (v1.x - v3.x) + (v3.x - v2.x) * (v1.y - v3.y));
    float lambda1 = ((v2.y - v3.y)*(X - v3.x) + (v3.x - v2.x)*(Y - v3.y)) / denonimator;
    float lambda2 = ((v3.y - v1.y)*(X - v3.x) + (v1.x - v3.x)*(Y - v3.y)) / denonimator;
    *l1 = lambda1;
    *l2 = lambda2;
    *l3 = 1 - lambda1 - lambda2;
}
$\endgroup$
3
  • $\begingroup$ It would be helpful to see the code for getBarycentricCoordinate. $\endgroup$
    – Reynolds
    Commented Feb 23, 2018 at 8:41
  • $\begingroup$ @Reynolds I just edit and add the code for getBarycentricCoordinate $\endgroup$ Commented Feb 23, 2018 at 15:41
  • $\begingroup$ What language are you using? Having negative barycentric coordinates means you're sampling outside of the triangle. $\endgroup$
    – flawr
    Commented Feb 24, 2018 at 22:57

1 Answer 1

1
$\begingroup$

I have figured out the solution to this, and want to share it. What I am doing is I calculate different barycentric coordinate for each of the step I need to do: z-buffer, interpolation of normal, etc.

The correct way is to use the barycentric coordinate that is calculated when checking z-buffer to test whether a pixel inside a triangle. Because that barycentric coordinate is guaranteed to be inside the [0, 1] range (otherwise the pixel wouldnt have been drawn), it is the correct barycentric coordinate to use.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.