Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SVGLoader - self-crossing semi-transparent paths show overlap, while original SVG doesn't #18791

Closed
3 tasks done
soadzoor opened this issue Mar 2, 2020 · 5 comments
Closed
3 tasks done

Comments

@soadzoor
Copy link
Contributor

soadzoor commented Mar 2, 2020

Hey,

Recently I've been playing around with the SVGLoader, and noticed that self-crossing semi-transparent paths show the overlap (like adding/mixing/blending the color), while the original SVG doesn't do this, see attached pic at the intersection below:

Original SVG:

overlap

Same SVG, as loaded with SVGLoader, and rendered with three.js:
overlap2

Is there any way I could get rid of this "color addition" at the intersection (while keeping the opacity), so it would look more like the original one?

Thank you

Live example:
https://jsfiddle.net/soadzoor/rps8v7a2/13/

Three.js version
  • r114
Browser
  • All of them
OS
  • All of them
@Mugen87
Copy link
Collaborator

Mugen87 commented Mar 2, 2020

The problem is that the self-crossing shape produces overlapping triangles. When configuring transparency for the material, the screenshot is the expected outcome.

Not sure if the shape can be triangulated differently so the overlapping does not occur.

@Mugen87 Mugen87 added the Loaders label Mar 2, 2020
@WestLangley
Copy link
Collaborator

This is a self-intersecting shape. I would not consider this a loader issue.

This is probably best resolved by using custom blending equations. There are likely a lot of ways to handle this. Here is one way, but you will have to adapt it to your use case.

// note: also set alpha:true in renderer constructor
    
blending: THREE.CustomBlending,

blendEquation: THREE.AddEquation,
blendSrc: THREE.SrcAlphaFactor,
blendSrcAlpha: THREE.OneFactor,
blendDst: THREE.ZeroFactor,

updated fiddle: https://jsfiddle.net/m6yawfcu/

@soadzoor
Copy link
Contributor Author

soadzoor commented Mar 2, 2020

@WestLangley Thank you for your response.

This is a self-intersecting shape. I would not consider this a loader issue.

Yea, you might be right, and it kind of makes sense to render it this way, but IMHO, in a perfect world, it should look exactly as the SVG itself.

I've just tried the workaround you came up with, but my problem with that, is that with these settings, blending is completely turned off. I put back the grid helper, so you can see what I mean:
https://jsfiddle.net/soadzoor/2L9sfhkx/2/

If it was possible somehow that the shape doesn't blend with itself, but it blends with everything else, that would be great.

Let me explain my use-case: I'm writing a highlighter-pen tool for a webapplication. It used to be based on CSS3DRenderer, and as you moved around the mouse with your mousebutton down, it used to create an svg path in the 3D space, with small (but nonzero) opacity, so it would look similar to how the drawing with a real-life highlighter-pen would look like.

Now, we're moving functionalities from the CSS3DRenderer to the WebGLRenderer (for non-related reasons), and currently I'm using the SVGLoader.pointsToStroke, which produces these visual artifacts (seen on the screenshot below), because of the overlappings (the green lines are the mouse-trace-coordinates, it's turned on for debugging purposes, the red shape is based on that entirely):
overlappings

So, in my case, it would be awesome if somehow it was possible to either:

  • Produce a set of vertices from the mouse-based coordinates, that are not overlapping with each other like this (like calculating the points at a given distance from the lines, and return them in proper winding order)
  • Create a set of blending rules that prevents blending with self, but uses "normal blending" with any other elements (not sure if possible)
  • Or any other idea is welcome. I've also tried using fat lines, based on this: https://threejs.org/examples/webgl_lines_fat.html , but it seems it doesn't support transparency at all

@WestLangley
Copy link
Collaborator

Alternatively,

depthFunc: THREE.LessDepth,
depthWrite: true,

https://jsfiddle.net/ut653xf9/

There are some artifacts if the camera rotates -- may improve if you tighten up the near/far planes.

This is not a help site, but maybe someone at the forum can help you if you need more help.

@soadzoor
Copy link
Contributor Author

soadzoor commented Mar 2, 2020

Okay, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants