<p>It sounds like what you need is a <a href="https://www.khronos.org/opengl/wiki/Scissor_Test" rel="nofollow noreferrer">scissor test</a>. It's specifically designed for clipping against an unrotated rectangle, and should be faster than messing about with the stencil buffer.</p>

CC BY-SA 3.0
2017-12-18T10:12:09.403Z
This works perfectly and is extremely fast, even though the GL driver of my Pi does not advertise ARB_viewport_array. Thank you!
Jonas Mechtheim
CC BY-SA 3.0
2017-12-18T05:02:41.307Z
2017-12-18T05:02:41.307Z
russ
<p>You could try clipping the polygons in code before you send them off to the renderer. Then you could avoid the stencil buffer entirely. To do this you could clip against all sides of the rectangle one at a time. I can't say for sure if this is faster than what you were doing before but here goes:</p>

<p>For this algorithm you need to represent a polygon as a list of points</p>

<p>How to clip against one side:</p>

<pre><code># careful of array out of bounds access
k = -1
# find first instance where a vertex is outside followed by one that is inside
for(i = 0; i &lt; verts.length; ++i)
    if(isOutside(verts[i]) &amp;&amp; !isOutside(verts[i + 1]))
        k = i
# if no such instance found
if(k == -1)
    if(isOutside(verts[0])) # entire thing outside
        return empty array
    else # entire thing inside
        return verts # return unchanged
# if instance was found
else
    newVerts = empty array
    # add first vertex in new shape
    newVerts.add(intersect(verts[k], verts[k + 1]))
    # walk the part of the polygon that is inside
    while(!isOutside(verts[++k]))
        newVerts.add(verts[k])
    # add last vertex in new shape
    newVerts.add(intersect(verts[k - 1], verts[k]))
    return newVerts
</code></pre>

<p>Then you could do something like:</p>

<pre><code>poly = clipLeftEdge(poly)
poly = clipRightEdge(poly)
poly = clipTopEdge(poly)
poly = clipBottomEdge(poly)
</code></pre>

<p>If the the original polygon was convex then the new one should be as well which means you could triangulate it or whatever you need before you draw.</p>

<p>A line which forms an edge of the clipping rectangle (if you extend it to be infinitely long) splits the entire space into 2 half spaces. You will need to provide a function to check whether a vertex is in the "inside" half space or the "outside" half space. Ex: left edge of rectangle is at x = -15. To check if the point is outside, do (point.x &lt; -15).</p>

<p>You will also need to provide a function to intersect 2 vertices. You have one vertex on the outside and one on the inside and somewhere in between there is a line that you want to clip against. For example if the left edge of the rectangle is at x = -15:</p>

<pre><code>factor = (-15 - p1.x)/(p2.x - p1.x)
newVertex.x = -15
newVertex.y = (p2.y - p1.y)*factor + p1.y
</code></pre>

<p>You will also need to linearly interpolate all other attributes you care about (like texture coordinates).</p>

<p>If you want to be really slick, you can write the clipping algorithm once and provide an appropriate isOutside and intersect function for each run.</p>

CC BY-SA 3.0
2017-12-18T05:35:40.620Z
2017-12-18T05:35:40.620Z
Chuck
<p>As per <a href="https://computergraphics.stackexchange.com/a/6004/209">Russ's answer</a>, I'd also suggest using scissor rectangles but, on the off-chance that is also slow, is it possible to use the Z buffer to set the Z to "near" in the regions you don't want drawn? </p>

<p>BTW, it would be useful to have an example image.</p>

CC BY-SA 3.0
2017-12-18T09:54:06.533Z
2017-12-18T09:54:06.533Z
Simon F
<p>I'm writing an OpenGL application that runs on a Raspberry Pi, i.e., a quite resource-limited system. Essentially, a few quads with RGBA textures are overlayed/alpha blended on top of each other with individual translation/rotation applied. They are clipped against an unrotated rectangle.</p>

<p>For this purpose, I currently use the stencil buffer. I.e., when drawing a texture which requires clipping, I clear the stencil buffer, render the clipping quad to the stencil buffer and enable the stencil testing before rendering the translated/rotated object.</p>

<p>On a Pi, clearing the stencil buffer is a painfully slow process in the order of 20ms, completely ruining performace. I thought about pre-rending the clipping rects to different bits of the stencil buffer, but that would lead to a maximum of 8 clipping regions (I need more).</p>

<p>Therefore, is there a different way of achieving clipping against a simple rectangle that does not require an expensive operation such as flushing the stencil buffer?</p>

<opengl><clipping><legacy-opengl><stencil-test><stencil-buffer>
Fast clipping without clearing stencil buffer
Jonas Mechtheim
# Fast clipping without clearing stencil buffer

(Asked by: username_0 on 2017-12-18)

I'm writing an OpenGL application that runs on a Raspberry Pi, i.e., a quite resource-limited system. Essentially, a few quads with RGBA textures are overlayed/alpha blended on top of each other with individual translation/rotation applied. They are clipped against an unrotated rectangle.

For this purpose, I currently use the stencil buffer. I.e., when drawing a texture which requires clipping, I clear the stencil buffer, render the clipping quad to the stencil buffer and enable the stencil testing before rendering the translated/rotated object.

On a Pi, clearing the stencil buffer is a painfully slow process in the order of 20ms, completely ruining performace. I thought about pre-rending the clipping rects to different bits of the stencil buffer, but that would lead to a maximum of 8 clipping regions (I need more).

Therefore, is there a different way of achieving clipping against a simple rectangle that does not require an expensive operation such as flushing the stencil buffer?

**Tags:** opengl, clipping, legacy-opengl, stencil-test, stencil-buffer


---

## 3 answers

### Answer by username_1 on 2017-12-18. Score: 1 | Accepted answer

It sounds like what you need is a [scissor test](https://www.khronos.org/opengl/wiki/Scissor_Test). It's specifically designed for clipping against an unrotated rectangle, and should be faster than messing about with the stencil buffer.

> **Comments:**
> **username_0**: This works perfectly and is extremely fast, even though the GL driver of my Pi does not advertise ARB_viewport_array. Thank you!  

---

### Answer by username_2 on 2017-12-18. Score: 0

You could try clipping the polygons in code before you send them off to the renderer. Then you could avoid the stencil buffer entirely. To do this you could clip against all sides of the rectangle one at a time. I can't say for sure if this is faster than what you were doing before but here goes:

For this algorithm you need to represent a polygon as a list of points

How to clip against one side:

```
# careful of array out of bounds access
k = -1
# find first instance where a vertex is outside followed by one that is inside
for(i = 0; i < verts.length; ++i)
    if(isOutside(verts[i]) && !isOutside(verts[i + 1]))
        k = i
# if no such instance found
if(k == -1)
    if(isOutside(verts[0])) # entire thing outside
        return empty array
    else # entire thing inside
        return verts # return unchanged
# if instance was found
else
    newVerts = empty array
    # add first vertex in new shape
    newVerts.add(intersect(verts[k], verts[k + 1]))
    # walk the part of the polygon that is inside
    while(!isOutside(verts[++k]))
        newVerts.add(verts[k])
    # add last vertex in new shape
    newVerts.add(intersect(verts[k - 1], verts[k]))
    return newVerts

```

Then you could do something like:

```
poly = clipLeftEdge(poly)
poly = clipRightEdge(poly)
poly = clipTopEdge(poly)
poly = clipBottomEdge(poly)

```

If the the original polygon was convex then the new one should be as well which means you could triangulate it or whatever you need before you draw.

A line which forms an edge of the clipping rectangle (if you extend it to be infinitely long) splits the entire space into 2 half spaces. You will need to provide a function to check whether a vertex is in the "inside" half space or the "outside" half space. Ex: left edge of rectangle is at x = -15. To check if the point is outside, do (point.x < -15).

You will also need to provide a function to intersect 2 vertices. You have one vertex on the outside and one on the inside and somewhere in between there is a line that you want to clip against. For example if the left edge of the rectangle is at x = -15:

```
factor = (-15 - p1.x)/(p2.x - p1.x)
newVertex.x = -15
newVertex.y = (p2.y - p1.y)*factor + p1.y

```

You will also need to linearly interpolate all other attributes you care about (like texture coordinates).

If you want to be really slick, you can write the clipping algorithm once and provide an appropriate isOutside and intersect function for each run.


---

### Answer by username_3 on 2017-12-18. Score: 0

As per [username_1's answer](https://computergraphics.stackexchange.com/a/6004/209), I'd also suggest using scissor rectangles but, on the off-chance that is also slow, is it possible to use the Z buffer to set the Z to "near" in the regions you don't want drawn?

BTW, it would be useful to have an example image.


---

