Edge finding and highlighting

A vanilla JS code for finding 3D geometry edges and visualizing them via custom shader.

Live example with UI:


Github repo:


// import THREE.js library

import { init } from 'edge_finder.js'

const config = {
   width: 0.2, 
   // border width, range [0, 1]
   alpha: true, 
   // solid mesh background
   invert: false, 
   // swap border/background style
   mode: 0, 
   // border style: 0 - solid, 1 - smooth, 2 - neon
   wave: 0, 
   // repeating border, 0 - disabled, recommended values [1, 2, 3, 4, ...]
   exp: 1, 
   // border falloff: 1 - smoothstep, 
   // otherwise exponential, recommended range [2, 100]

const mesh = init( // returns THREE.Mesh
   // buffer geometry, indexed geometry will be converted to non-indexed
   // edge detection precision in range (0, 1), 
   // higher values detect sharper edges only
   // matching vertice positions detection precision 
   // (for example, along uv seams)

Object config will be interactive, any changes to its properties will be reflected in real time on the next mesh render.


It’s good.

Do you plan to make the width consistent? Currently, if it is applied to a 1x1x1 cube, the width is OK, but for 10x1x1 cuboid it is stretched along X.

Good point, some extra code will be needed to adjust the width depending of the triangle ratios as well. I’ll add it to TODO list :wink:

1 Like

Cool, reminds me of this of this repo, with a slightly different result.

Any plans on making a minimal documentation?

Very nice, I was thinking about adding more ways to visualize borders, that gives me some ideas.

The main difference is that I don’t identify quads, I detect if line segments belong to two coplanar triangles, so any flat shape will not have visualized edges inside it (like the ring in the example).

I can add some doc-like description here, you are interested in finding edges or visualization?

1 Like

I’m interested in everything related to three.js :smile:

ok, I’ll add it tomorrow

1 Like

Thank you, but please don’t feel obliged, although instructions are always welcome the source code in your demo is clear enough.

You may add the ring example in your TODO list too. Sometimes borders are needed for vertices, not only for edges.



If I make borders the same width, they will not match, and I don’t want to make the shader code way more complex and slow, so I’m going to call it a feature not a bug and leave it as is for now.

The solution for long large polygons is currently to divide them, for example:

new THREE.PlaneGeometry(2*sz, sz, 2, 1),


1 Like

The problem with notches has been solved and the code updated:


also added monkey head for more complex geometry test:




First, all the required info about segments is gathered, each triangle is considered to be made out of 3 segments:


Each segment can be a part of one or two triangles. For each of these triangles a normal is calculated and if all the normals are parallel to each other to a certain (customizable) degree, the segment is not an edge, otherwise it is.


The visualization is based on interpolation of vertex attributes, namely, RGB colors. Each segment is associated with one RGB channel and, in case the segment is an edge, a gradient (from 1 to 0) is created in that channel, that can then be used for creating visuals in the fragment shader.


in case the segment is not an edge, there is no gradient.


this info is stored in clr / vclr attribute.

To remove notches, some vertices assigned values of another clr2 / vclr2 attribute, to create similar gradient, based on the observation that if a segment has a gradient of vclr in any of the triangles it belongs to, there will be “a notch situation” that needs to be resolved.


The code is not really optimized for speed, but you can run it once “offline”, print out clr and clr2 attributes and hardwire them back to your program, in this case you don’t need the code.


@tfoller :exploding_head:

When I asked for instructions, I was talking about a simple Github style documentation.

// Usage
Import { method } from "lib"
const result = method(x)

But you went with a thorough explanation, this can be a draft for a premium level medium article. Thank you very much for your kindness and taking the time instructing a fellow three.js pal, I definitely learned something new here and for sure it will come in handy in the future.

1 Like

Added a nicer exponential falloff on top of smoothstep and repetitive borders:


as well as a github repo, see the OP.

1 Like