Rounded sprite over lines (black corners, etc)

Hello!

I trying to draw a simple linked graph with circle sprites as nodes.

Sometimes I can see black corners around the circles:
%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5

https://codepen.io/aleksanderd/pen/VVzWGd

I think, the corners is not really black, the problem seems to be since some part of lines (behind the “black” corners) not visible (while other sprites visible ok).

Also I noticed the problem appears only for far nodes groups… No any problem with nodes between center of the world and the camera. And even far nodes sometimes ok(presumably, if there is no any objects before).

Another problem: sometimes, if a transparent line over sprite, it is rendered as transparent crack at sprite(so I can see through this crap objects behind the sprite).

The sprites images created using canvas2d with transparent corners.
The lines is BufferGeometry with simple shaders. The same troubles if draw lines sepratelly(w/o BufferGeometry).

I tried to explore THREE.Sprite, etc sources but not found any solutions/ideas.

What the root problem(s): in sprites or in lines? Any help welcome!

Thank you!

How do you create your SpriteMaterial? Besides, do you mind to demonstrate the issue with a live demo?

typescript code:

...
  public createObject(): THREE.Object3D {
    let obj;
    const scale = this.graph3d.params.nodeScale;
    obj = this.createSprite();
    obj.scale.set(this.size * scale, this.size * scale, this.size * scale);
    obj.castShadow = true;
    obj.receiveShadow = true;
    return obj;
  }

  private createSprite(): THREE.Object3D {
    const circle = this.createNodeCircle(); // default image while awaiting real image loading
    let texture: THREE.Texture;
    texture = new THREE.TextureLoader().load(circle.image, async (t) => {
      await this.applyTextureImage(t, this.model.image);
    });
    const material = new THREE.SpriteMaterial({
      map: texture,
    });
    return new THREE.Sprite(material);
  }

  private async applyTextureImage(
    texture: THREE.Texture,
    image?: string,
  ): Promise<THREE.Texture> {
    let img: string = image || defaultImage;
    if (img.includes(defaultImagePattern)) {
      img = defaultImage;
    }
    return new Promise<THREE.Texture>((resolve, reject) => {
      const tLoader = new THREE.TextureLoader();
      tLoader.load(
        img,
        (t: THREE.Texture) => {
          const circle = this.createNodeCircle(t.image);
          tLoader.load(circle.image, (it: THREE.Texture) => {
            texture.image = it.image;
            texture.format = it.format;
            texture.needsUpdate = true;
            resolve(texture);
          });
        },

      );
    });
  }

  private createNodeCircle(image?: CanvasImageSource) {
    const canvas = new Canvas(); // custom helper to init/work with canvas2d
    const size = 256;
    canvas.element.width = size;
    canvas.element.height = size;
    const ctx = canvas.context;

    const centerX = size / 2;
    const centerY = size / 2;
    const radius = size / 2;
    ctx.beginPath();
    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
    if (image) {
      ctx.closePath();
      ctx.clip();
      ctx.drawImage(image, 0, 0, size, size);
      ctx.beginPath();
      ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
    } else {
      ctx.fillStyle = '#F9FFD9';
      ctx.fill();
    }
    ctx.lineWidth = 5;
    ctx.strokeStyle = 'white';
    ctx.stroke();
    return canvas;
  }

...

Unfortunately, I can not publish the code yet, I will try to create some for tests but it will take a time…

Thank you!

What happens if you create your sprite material like so:

const material = new THREE.SpriteMaterial({
    map: texture,
    depthWrite: false
});
2 Likes

exactly! :crazy_face:

depthWrite: false solves the problem. huge thnx!

1 Like

just added depthWrite: false to links material and second problem gone too.

going to learning more about this parameter, thnx :slight_smile:

Unfortunately, there is another strange effects :frowning:

If set depthWrite to false, “black” corners are gone, but the nodes still abruptly change color/lightness while rotating the scene. Here is example (you can set depthWrite = false at first lines):

I think about to not use sprite at all, but create 3d circle with needed image texture - there is no such problems with 3d objects.

But I am interesting, what the root of the problem? It seems to be correlated to z-asix zero, and may be there is some parameter unknown for me…

Also, I noticed strange effects while playing with near parameter of PerspectiveCamera.
There is no “black” corners if set near of the camera to 0.0000001! The corners returns for any bigger values(even for 0.000001[5 zeros instead of 6]) and sometimes it causes strangle flickering of links/nodes…

Resuming:

depthWrite = true, near = 0.1 - “black” corners + nodes lightness artifacts while rotating
depthWrite = false, near = 0.1 - no corners, only nodes lightness artifacts
depthWrite = true, near = 0.0000001 - no corners, but looks like links are not transparent (at least at zoom out)
0.0000001 > near > ~~0.001 - strange flickering

Could you clear it for me plz?

  1. What the magic plate at z-axis zero? Before it all ok, farther - artifacts.
  2. How camera’s near option changes the render result so strange?

Thank you!