0

So I'm trying to "outline" 3D objects. Standard problem, for which the answer is meant to be that you copy the mesh, color it the outline color, scale it up, and then set it to only render faces that are "pointed in the wrong direction" - for us that means setting side:THREE.BackSide in the material. Eg here https://stemkoski.github.io/Three.js/Outline.html

But see what happens for me here

Here's what I'd like to make lines filled in

I have a bunch of objects that are close together - they get "inside" one another's outline.

Any advice on what I should do? What I want to be seeing is everywhere on the rendered frame that these shapes touch the background or each other, there you have outline.

2
  • 1
    Have a look at the source code of this example Commented Mar 11, 2017 at 18:26
  • The sample you linked to has the exact same problem as the question Commented Mar 13, 2017 at 5:45

1 Answer 1

1

What do you want to happen? Is that one mesh in your example or is it a bunch of intersecting meshes. If it's a bunch of intersecting meshes do you want them to have one outline? What about other meshes? My point is you need some way to define which "groups" of meshes get a single outline if you're using multiple meshes.

For multiple meshes and one outline a common solution is to draw all the meshes in a single group to a render target to generate a silhouette, then post process the silhouette to expand it. Finally apply the silhouette to the scene. I don't know of a three.js example but the concept is explained here and there's also many references here

Another solution that might work, should be possible to move the outline shell back in Z so doesn't intersect. Either all the way back (Z = 1 in clip space) or back some settable amount. Drawing with groups so that a collection of objects in front has an outline that blocks a group behind would be harder.

For example if I take this sample that prisoner849 linked to

And change the vertexShaderChunk in OutlineEffect.js to this

  var vertexShaderChunk = `

    #include <fog_pars_vertex>

    uniform float outlineThickness;

    vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {

      float thickness = outlineThickness;
      const float ratio = 1.0; // TODO: support outline thickness ratio for each vertex
      vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + objectNormal, 1.0 );
    // NOTE: subtract pos2 from pos because BackSide objectNormal is negative
      vec4 norm = normalize( pos - pos2 );

   // ----[ added ] ----

      // compute a clipspace value
      vec4 pos3 = pos + norm * thickness * pos.w * ratio;

      // do the perspective divide in the shader
      pos3.xyz /= pos3.w;

      // just return screen 2d values at the back of the clips space
      return vec4(pos3.xy, 1, 1);

    }

  `;

It's easier to see if you remove all references to reflectionCube and set the clear color to white renderer.setClearColor( 0xFFFFFF );

Original:

enter image description here

After:

enter image description here

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you gman! But I'm afraid to say these are multiple meshes - and I am looking for multiple outlines. The shader will need a clever "edge detector" that will detect anywhere that a color touches something else that is not its own color. Does such a thing exist? If it does I can see it is much more advanced than the solutions I have seen... and yet... surely I'm not the first person to want two thickly-outlined things to touch?
Maybe you should add a hand created image of what you're trying to achieve
Added now :o in some sense I'm just trying to get rid of "glitches"
The only things I can think of are (a) run an edge detection post process on the image then run another shader over the result to expand the edges and then use that as a mask to draw the outlines. (b) draw each object one at a time, then draw its outline, then the next object, then it's outline rather than drawing all the objects then all the outlines (not sure that would work actually)
Thanks all the same. The second one wouldn't work, because imagine one object hooked around another! What I'm going to do is very much a cheat: I'm reducing the size of the pieces, and their outlines will take up the space currently taken up by their actual size. This solves my problem, in this case!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.