<p>You need to add clipping.</p>
<p>When a vertex goes behind the near plane in camera space, it still gets projected to the screen which leads to these issues. You need to find where the edges of your triangle intersect with the near plane and edit the triangle in order to make all the vertices in front of the near plane.</p>
<p><a href="https://gabrielgambetta.com/computer-graphics-from-scratch/11-clipping.html" rel="nofollow noreferrer">This</a> is a good resource for more information.</p>
<p>Get the line-plane intersect algorithm from <a href="https://stackoverflow.com/questions/5666222/3d-line-plane-intersection">here</a>. Here's some untested psudocode to get you started</p>
<pre><code>for (worldTri of Scene)
   camTri = worldTri.toCamSpace()

   clipped = []

   for (vertex of camTri)
      clipped.push(vertex.z &gt; near)

   numClipped = clipped.filter(a =&gt; a).length // get number of clipped vertices
   clippedTris   

   if (numClipped === 3) clippedTris = [camTri]
   if (numClipped === 2)
      clippedTris = [
         new tri(
            clipped[0] ? camTri[0] : linePlaneIntersect(camTri[0], camTri[1]),
            clipped[1] ? camTri[1] : linePlaneIntersect(camTri[1], camTri[2]),
            clipped[2] ? camTri[2] : linePlaneIntersect(camTri[2], camTri[0])
         ),
         new tri(
            clipped[0] ? camTri[0] : linePlaneIntersect(camTri[0], camTri[2]),
            clipped[1] ? camTri[1] : linePlaneIntersect(camTri[1], camTri[0]),
            clipped[2] ? camTri[2] : linePlaneIntersect(camTri[2], camTri[1])
         )
      ]
   if (numClipped === 1)
      clippedTris = [
         new tri(
            clipped[0] ? camTri[0] : linePlaneIntersect(camTri[1], camTri[2]),
            clipped[1] ? camTri[1] : linePlaneIntersect(camTri[0], camTri[2]),
            clipped[2] ? camTri[2] : linePlaneIntersect(camTri[0], camTri[1]),
         )
      ]
   if (numClipped === 0) clippedTris = []

   for (clipTri of clippedTris)
      clipTri.doTheRestOfYourRasterizationAsIfThisWasAlreadyTransformedIntoCamSpace()
</code></pre>

CC BY-SA 4.0
2022-11-01T15:02:00.927Z
2022-11-01T15:02:00.927Z
RKM
<p>I've been trying to make a simple rasterizer in JS, and it's working well except for this one bug. (<a href="https://i.sstatic.net/8BPc8.jpg" rel="nofollow noreferrer">Example</a>) Here is part of the fragment shader, as I believe that's where something is going wrong (If it is the vertex shader I'll edit my question with that code as well)</p>
<pre><code>let bounds = rasterTri.getBoundingBox(canvas.width, canvas.height)

if (!bounds) {continue}

let area = edgeFunction(rasterTri.a, rasterTri.b, rasterTri.c)

let diffuse = worldTri.normal().dot(lightDir)
        
for (let y = bounds.y0; y &lt;= bounds.y1; ++y) { 
   for (let x = bounds.x0; x &lt;= bounds.x1; ++x) {
      let pixel = new vec3(x+0.5, y+0.5, 0)

      let w0 = edgeFunction(rasterTri.b, rasterTri.c, pixel)
      let w1 = edgeFunction(rasterTri.c, rasterTri.a, pixel)
      let w2 = edgeFunction(rasterTri.a, rasterTri.b, pixel)
                
      if (w0 &gt;= 0 &amp;&amp; w1 &gt;= 0 &amp;&amp; w2 &gt;= 0) {
         w0 /= area
         w1 /= area
         w2 /= area
         let z = 1 / (rasterTri.a.z * w0 + rasterTri.b.z * w1 + rasterTri.c.z * w2)

         if (z &lt; depthBuffer[y * canvas.width + x] &amp;&amp; z &gt; near) {
            depthBuffer[y * canvas.width + x] = z
            let index = y * (canvas.width*4) + (x*4)

            pixels[index+0] = 255*diffuse
            pixels[index+1] = 0
            pixels[index+2] = 0
            pixels[index+3] = 255
         }
      }
   }
}
</code></pre>
<p>I'm trying to follow <a href="https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation" rel="nofollow noreferrer">this</a> tutorial but clearly something got lost in translation, any help would be greatly appreciated!</p>

<rasterizer><debugging>
Unexpected behavior when polygon goes off the side of the camera
PersonMon
# Unexpected behavior when polygon goes off the side of the camera

(Asked by: username_0 on 2022-10-26)

I've been trying to make a simple rasterizer in JS, and it's working well except for this one bug. ([Example](https://i.sstatic.net/8BPc8.jpg)) Here is part of the fragment shader, as I believe that's where something is going wrong (If it is the vertex shader I'll edit my question with that code as well)

```
let bounds = rasterTri.getBoundingBox(canvas.width, canvas.height)

if (!bounds) {continue}

let area = edgeFunction(rasterTri.a, rasterTri.b, rasterTri.c)

let diffuse = worldTri.normal().dot(lightDir)
        
for (let y = bounds.y0; y <= bounds.y1; ++y) { 
   for (let x = bounds.x0; x <= bounds.x1; ++x) {
      let pixel = new vec3(x+0.5, y+0.5, 0)

      let w0 = edgeFunction(rasterTri.b, rasterTri.c, pixel)
      let w1 = edgeFunction(rasterTri.c, rasterTri.a, pixel)
      let w2 = edgeFunction(rasterTri.a, rasterTri.b, pixel)
                
      if (w0 >= 0 && w1 >= 0 && w2 >= 0) {
         w0 /= area
         w1 /= area
         w2 /= area
         let z = 1 / (rasterTri.a.z * w0 + rasterTri.b.z * w1 + rasterTri.c.z * w2)

         if (z < depthBuffer[y * canvas.width + x] && z > near) {
            depthBuffer[y * canvas.width + x] = z
            let index = y * (canvas.width*4) + (x*4)

            pixels[index+0] = 255*diffuse
            pixels[index+1] = 0
            pixels[index+2] = 0
            pixels[index+3] = 255
         }
      }
   }
}

```

I'm trying to follow [this](https://www.scratchapixel.com/lessons/3d-basic-rendering/rasterization-practical-implementation) tutorial but clearly something got lost in translation, any help would be greatly appreciated!

**Tags:** rasterizer, debugging


---

## 1 answers

### Answer by username_1 on 2022-11-01. Score: 2 | Accepted answer

You need to add clipping.

When a vertex goes behind the near plane in camera space, it still gets projected to the screen which leads to these issues. You need to find where the edges of your triangle intersect with the near plane and edit the triangle in order to make all the vertices in front of the near plane.

[This](https://gabrielgambetta.com/computer-graphics-from-scratch/11-clipping.html) is a good resource for more information.

Get the line-plane intersect algorithm from [here](https://stackoverflow.com/questions/5666222/3d-line-plane-intersection). Here's some untested psudocode to get you started

```
for (worldTri of Scene)
   camTri = worldTri.toCamSpace()

   clipped = []

   for (vertex of camTri)
      clipped.push(vertex.z > near)

   numClipped = clipped.filter(a => a).length // get number of clipped vertices
   clippedTris   

   if (numClipped === 3) clippedTris = [camTri]
   if (numClipped === 2)
      clippedTris = [
         new tri(
            clipped[0] ? camTri[0] : linePlaneIntersect(camTri[0], camTri[1]),
            clipped[1] ? camTri[1] : linePlaneIntersect(camTri[1], camTri[2]),
            clipped[2] ? camTri[2] : linePlaneIntersect(camTri[2], camTri[0])
         ),
         new tri(
            clipped[0] ? camTri[0] : linePlaneIntersect(camTri[0], camTri[2]),
            clipped[1] ? camTri[1] : linePlaneIntersect(camTri[1], camTri[0]),
            clipped[2] ? camTri[2] : linePlaneIntersect(camTri[2], camTri[1])
         )
      ]
   if (numClipped === 1)
      clippedTris = [
         new tri(
            clipped[0] ? camTri[0] : linePlaneIntersect(camTri[1], camTri[2]),
            clipped[1] ? camTri[1] : linePlaneIntersect(camTri[0], camTri[2]),
            clipped[2] ? camTri[2] : linePlaneIntersect(camTri[0], camTri[1]),
         )
      ]
   if (numClipped === 0) clippedTris = []

   for (clipTri of clippedTris)
      clipTri.doTheRestOfYourRasterizationAsIfThisWasAlreadyTransformedIntoCamSpace()

```


---

