Making an arbitrary polygon look darker towards the edges

I am writing an application which displays 2d polygons. My application is in Java and uses jme3 / LWJGL at the higher levels but I don't think that changes much, my question is at the GL level.

The 2d polygons have dozens of vertices and the shape of the polygon, including the number and position of vertices, changes a little with each rendered frame. The polygons cannot be assumed to be convex, but they are contiguous, don't have holes, and the path defining each polygon does not ever cross itself.

Each frame, I'm breaking each polygon down to a set of triangles using a 3rd party java library. Then I'm sending these triangles to OpenGL to be rendered.

Currently I'm displaying each polygon with just one unshaded color.

What I want is to smoothly darken that color towards the edge of the polygon. That is, the closer a pixel is to the nearest point on the boundary of the polygon, the darker it should be, according to some formula relating the distance with the darkness.

I don't know what this kind of effect is called so I've struggled to find any design ideas on the web. I'm looking for any pointers or links to achieving this effect, in general terms. Even "this is known as the XYZ problem". Or any general ideas as to how I would achieve this.

I believe what you are looking for is called pillow shading. You could do it by making an alpha-only copy of the polygon, blur it, and then render the original polygon again using a shader that reads the blurred texture intensity and multiplies it by the polygon color.

Thanks for those quick responses. That's certainly given me some ideas.

Originally Posted by cireneikual

I believe what you are looking for is called pillow shading. You could do it by making an alpha-only copy of the polygon, blur it, and then render the original polygon again using a shader that reads the blurred texture intensity and multiplies it by the polygon color.

Originally Posted by yoyonel

Hello,

For visual effect, you can:
- [1] Use a Stencil Buffer (and stencil operations) and render your polygons and mark them (for example 1 for 'inside" polygon)
- [2] Render in a target your edges
- [3] Blur this RT [2]
- [4] Inverse the RT [3]
- [5] Use the StencilBuffer [1] to apply result of your RT [4] and mix the color result (darker towers the edges)

A simple way =>
Use a shader (pixel shader, fragment shader) when you're rendering your triangle to compute the distance between the pixel/point and the "base"-edge of your triangle.
Point-Line distance is a simple computation, you only need to know the "good" edge for each triangle, and use this distance to smooth your render color.

A simple way =>
Use a shader (pixel shader, fragment shader) when you're rendering your triangle to compute the distance between the pixel/point and the "base"-edge of your triangle.
Point-Line distance is a simple computation, you only need to know the "good" edge for each triangle, and use this distance to smooth your render color.

YoYo

Thanks yoyo!

This seems like the best method. For each triangle I can pass to the shader a subset of the polygon boundary edges. The shader can then compute the minimum length vector between the current pixel location and one of these polygon boundary edges. It can then use this vector to compute the color / alpha values or look them up in a texture.

As a potential optimization, in my application (i.e. outside the shader code) I can narrow down the boundary edges to a subset which includes only those edges which are the closest edge to some pixel in the triangle.

The code below addresses your problem using Classic GL (fixed pipeline) and some math routines which are included. It carefully extrudes the poly edges inward making quads, then uses simple color interpolation to fade the quads from inner to outer edge. Source code and figure are included. There are some Gouraud shading artifacts. Plus I've only tested it for this fairly simple polygon. I leave it up to you to do more testing. Not sure how contorted your polys are. This algorithm assumes the vertices of a poly are listed in counterclockwise order. To get the effect I think you want, draw the polys twice: 1) use your technique to draw the poly filled with solid color, 2) draw again with my technique to fade the edges. Let me know if it works for you!