SphereGeometry with 2D Outline

Hello,

Is there any possability to create an outline around a SphereGeometry which looks 2D and also rotate dynamically, so that when i move the camera (OrbitsControls) the outline is always correctly visible?

Something like this:

image

This is a little bit unclear for me… because hard to imagine when object 2D rotating in 3D scenario, classical scenario…

But anyway… you can make fake outline, by cloned mesh, for example…

  const g = new THREE.SphereGeometry(1, 64, 64);
  const m = new THREE.MeshBasicMaterial({ color: 0x69DBFF });
  const sphere = new THREE.Mesh(g, m);
  scene.add(sphere);

  const outlineM = new THREE.MeshBasicMaterial({
    color: 0x000000,
    side: THREE.BackSide
  });
  const outline = new THREE.Mesh(g.clone(), outlineM);
  outline.scale.set(1.15, 1.15, 1.15);
  sphere.add(outline);

https://codepen.io/Lucas_Mas/pen/PwwJNap?editors=0010

or you can use Outline Pass…

3 Likes

The reference image looks like that you could just use sprites instead of spheres and outlines.

https://codepen.io/boytchev/full/QWJOBrL

image

7 Likes

It may not be that simple, because the circular outline of a sphere devolves into an ellipse-like shape when projected onto a (oblique) plane:

My suggestion is to use a sprite instead of the sphere and its outline altogether, not just the outline.

2 Likes

@PavelBoytchev : I’m in fact a little confused by the co-existence of “sphere” (a 3D entity) which looks “2D” and a “2D outline” in the TO’s requirements. :thinking:

your approach is exactly what i wanted, but when i try it i get this:

image

Here is my Code:


    geometry = new THREE.SphereGeometry(0.1, 32, 32);
    material = new THREE.MeshBasicMaterial({
      color: color,
      depthTest: false,
      opacity: 1,
      visible: true,
    });

    const sphere = new THREE.Mesh(geometry, material)
    if (tag) sphere.userData.tag = tag;
    sphere.position.copy(position)
    scene.add(sphere)

    const outlineM = new THREE.MeshBasicMaterial({
      color: 0x000000,
      side: THREE.BackSide
    });
    const outline = new THREE.Mesh(geometry.clone(), outlineM);
    outline.scale.set(1.15, 1.15, 1.15);
    sphere.add(outline);

i tried it with the sprite approach, but they appear stretched and pixelated:

my code:

var canvas = document.createElement( 'CANVAS' );
    canvas.width = 64;
    canvas.height = 64;

    var context = canvas.getContext( '2d' );
    context.lineStyle = 'black';
    context.lineWidth = 3;
    context.fillStyle = 'white';
    context.beginPath();
    context.arc( 32, 32, 6, 0, 2*Math.PI );
    context.fill( );
    context.stroke( );

    var texture = new THREE.CanvasTexture( canvas )
    var material = new THREE.SpriteMaterial( {
        transparent: true,
        opacity: 1,
        depthTest: false,
        map: texture,
      } );
    var sprite = new THREE.Sprite( material );
    sprite.position.copy(position);
    scene.add( sprite )

There could be various reasons for these, but as you are the only one who can debug the code, it is up to you to find the actual cause and fix it. For example, stretching could be caused by unadjusted perspective matrix, and pixelation is because the circle in the texture is too small (the radius is just 6 pixels).

2 Likes

Could you make your CodePen with that?

2 Likes

ok so i made a codepen and it works: https://codepen.io/LordMaddhi/pen/OPPOQzM?editors=0011

i figured out that it my project it works when i delete the
sphere.position.copy(position) line.

i logged the position:
Vector3 {x: -0.02214988201910069, y: -0.0039832370587698784, z: -0.01780832572595914}

what could be the problem?

sphere.position.copy(new THREE.Vector3(-1, -1, -1))

This line displaces the sphere from the coordinate origin, which btw. coincides with the default OrbitControls.target.

As long as the sphere is placed at the target position of the orbiting camera, you’ll be looking at it straight on, and it will be displayed in the center of your screen/window. And there will be no reason for skewing.

If you have an offset between the sphere position and the OrbitControls.target, you will fall victim to the effect that @PavelBoytchev describes in his post which I linked in post #4 of this thread.

Deleting the sphere.position.copy(…) line makes the effect go away by re-aligning the sphere position with the OrbitControls.target. But the skewing is easily re-introduced by moving the OrbitControls.target away from the coordinate origin instead. See the modified Codepen for reference:

https://codepen.io/Chrisssie/pen/xbbPjOg

1 Like

but skewing is not the problem here, its this weird effect described in post #8 or is this a result of skewing?

“stretching” and “skewing” are synonyms in this context. The “pixelated” look is gone, as far as I can tell.

i mean that:
image

This effect is not visible in your Codepen. For further ideas, please supply a Codepen which displays this issue.

Hi @lordmaddhi …
I took your codepen
https://codepen.io/LordMaddhi/pen/OPPOQzM?editors=0011
change the radius to 1 and got…

thanks guys! i fixed it :slight_smile: