Unwrapping a custom ShapeBufferGeometry

Hi, I’m trying to use a shader to get an inset border in some custom geometries, but it turns out to be a big task for me.

Not sure if I’m not implementing the effect correctly or maybe the custom shapes need to be unwrapped in a specific way (or both).

This is my post in StackOverflow: three.js - ThreeJS: Problem implementing 'non-ThreeJS' shader - Stack Overflow

Are the custom shapes’ UVs automatically unwrapped after being created or they need an specific unwrapping for ellipses, triangles, etc.?

If they are not unwrapped, it would be nice to have some unwrapping methods in some ‘utils’ class for noobs like me. Thanks for all your work on this engine.

As far as I know, shape UVs are world coordinates.

If it’s of any help, I once wrote some shaders for different types of shape “vector” gradients, including “contour” gradient, that could be used to create borders, after some modification.


1 Like

Thanks for your reply. Your function ‘pointInTriangle’ seems to be what I need to get the shape’s border.
However, I struggle to get the points from my custom shapes. Either I’m not using the correct method or they are not in the order needed for this:

First of all, this shader was not designed to create borders, it creates contours and has a convergence point inside a shape, where all gradients meet. It will look like a border if the shape is symmetrical but not in other cases. So for borders you need to come up with a different approach.


The idea here is to provide a shape border as a collection of line segments in the same space as UVs and then colorize the distance from the current uv point (pixel) to the nearest border segment (line). For that the uv origin needs to be inside the shape.

Function pointInTriangle builds a triangle from the beginning and the end of a polygon segment ( a line) and the origin point. Then it checks if the current pixel uv coordinates belong to the triangle, if they do then calculates the distance.

It’s like raycasting from the center of the shape to all border vertices to make triangles and then calculate a distance inside the chosen triangle. The result depends on where the center is and how curvy the shape is. It will not work for any shape.

Lines are made of separate segments, for a triangular shape made out of 3 points [A,B,C], lines need to be in the format [A,B, B,C, C,A].

Making lines out of position array is tricky because there might be vertices in the middle of the shape which are not the part of the shape borderline. Also, shapes might have seams for uv unwrapping, so some vertices will be duplicated. Thus some manual cleanup might be needed.

On top of that you need to know where the center of the uv coordinate system is and make adjustments to uv values and line values to keep them centered, the way I did it for the heart shape.

For shapes uvs are not normalized, they will be vertices world coordinates.

Uv origin depends on how the shape was created, for example for ellipse and heart shape uvs originally will be set like this, so the heart shape needs adjustment:


You can use these two lines to see each of the shapes:

createEllipse(); // ellipse
//createEllipse(hgeom); // heart
1 Like

Thanks very much for your very detailed reply! It is really useful! I’ve been really stuck with this, and I can make progress again now.