<p>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. </p>

<p>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.    </p>

CC BY-SA 3.0
2018-02-25T00:38:52.080Z
2018-02-25T00:38:52.080Z
Manh Nguyen Huu
<p>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. </p>

<p>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.</p>

<pre><code>for (int Y = minY; Y &lt;= maxY; Y++) {
    for (int X = minX; X &lt;= maxX; X++) {
        float lambda1, lambda2, lambda3;
        getBarycentricCoordinate(v1, v2, v3, X, Y, &amp;lambda1, &amp;lambda2, &amp;lambda3);
        if ((0.0f &lt;= lambda1 &amp;&amp; 0.0f &lt;= lambda2 &amp;&amp; 0.0f &lt;= lambda3)) {
            float zValue = lambda1 * zA + lambda2 * zB + lambda3 * zC;
            if (abs(zValue) &lt; 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, &amp;lamb1, &amp;lamb2, &amp;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;
            }
        }
    }
}
</code></pre>

<p>Below is the code for my barycentric coordinate</p>

<pre><code>void getBarycentricCoordinate2D(Vector3f &amp; v1, Vector3f &amp; v2, Vector3f &amp; 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;
}
</code></pre>

CC BY-SA 3.0
2018-02-23T08:41:46.640Z
It would be helpful to see the code for getBarycentricCoordinate.
Reynolds
CC BY-SA 3.0
2018-02-23T15:41:40.333Z
@Reynolds I just edit and add the code for getBarycentricCoordinate
Manh Nguyen Huu
CC BY-SA 3.0
2018-02-24T22:57:21.890Z
What language are you using? Having negative barycentric coordinates means you're sampling *outside* of the triangle.
flawr
<3d><lighting>
How to interpolate vertex normals for Phong lighting when barycentric coordinates are negative?
Manh Nguyen Huu
# How to interpolate vertex normals for Phong lighting when barycentric coordinates are negative?

(Asked by: username_0 on 2018-02-23)

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;
}

```

**Tags:** 3d, lighting

> **Comments:**
> **username_1**: It would be helpful to see the code for getBarycentricCoordinate.  
> **username_0**: @username_1 I just edit and add the code for getBarycentricCoordinate  
> **username_2**: What language are you using? Having negative barycentric coordinates means you're sampling *outside* of the triangle.  

---

## 1 answers

### Answer by username_0 on 2018-02-25. Score: 1

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.


---

