-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
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
Improve performance of SVGRenderer #11359
Conversation
Idea to use svg:path for all SVG primitives. Later one can concatenate svg:path if they have identical styles
Replace it by svg:rect
Now rendering of all elements done with svg:path
If several svg:path with same style should be created, just concatenate there 'd' attributes and make single svg:path node. Will highly reduce size of SVG if many elements with similar color should be rendered.
When SVG stored into the file, reduces file size by ~5%
Avoid explicit usage of fill-opacity or stroke-opacity One could provide similar function in THREE.Color object itself
While SVG is text format, 10-digits for each coordinate is overkill. In many cases on can use precion=1 or even precision=0. For instance, instead of path d="M95.67875432291896,61.48774395485388L99.22967055503229,-179.38931463976644" one gets (with precision 1) path d="M95.7,61.5L99.2,-179.4" This significantly (factor 2) reduces size of SVG when stored into the file.
examples/js/renderers/SVGRenderer.js
Outdated
|
||
function convert ( c ) { | ||
|
||
return _precision < 0 ? c : c.toFixed(_precision); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about setting _precision
to null
by default and here check for _precisions !== null
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 0daa689
commit
examples/js/renderers/SVGRenderer.js
Outdated
@@ -220,6 +241,8 @@ THREE.SVGRenderer = function () { | |||
|
|||
} | |||
|
|||
addPath ( "!dummy!", ""); // just to flush last svg:path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about doing a clearPath()
function instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I call function flushPath() - it is used also in addPath()
Such method can be used directly at the end of rendering loop
|
||
if ( opacity === undefined || opacity === 1 ) return 'rgb(' + arg + ')'; | ||
|
||
return 'rgba(' + arg + ',' + opacity + ')'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, similar approach can be used THREE.Color.getStyle().
One could add opacity parameter to the function and return rgba() string if opacity defined and not equal to 1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you done benchmarks on this? Maybe the browser is already doing the same check internally?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reduces size of SVG string - when written into the file.
I do not think that it has any significant impact on performance
Sweet! Thanks! |
Addresses first part of #11356
Main idea - always use svg:path for rect, line or triangle rendering.
If consequent elements have similar style, just concatenate them.
Plus several more optimizations:
Depending from geometry, can speed up SVG generation by factor 20 and reduce SVG size by factor 4