Hi, thanks for the work on this library.
After integrating a similar renderer into my own engine and profiling dense modcharts, I noticed that a big part of the FPS drop comes from per-frame allocations and repeated path work inside the renderer hot path.
I think there are a few optimization opportunities that could help a lot without changing the public API:
Reuse static index and UV buffers for arrows, holds and paths instead of rebuilding them inside prepare calls.
Reuse scratch objects like Vector3, ArrowData and temporary transform data instead of allocating them every frame.
Avoid repeated cloning or fresh vector creation inside hold/path loops when the base position can be reused.
Rebuild hold/path geometry buffers only when subdivision count or path resolution actually changes.
Consider optional adaptive sustain subdivisions when FPS stays low for several frames.
Expose lightweight renderer stats for profiling, such as draw command count, active holds, vertex count and emission time.
I applied similar changes on my side and it noticeably reduced FPS drops (Almost a hold that's too long would drop between 0 and 2 fps --> 120fps - 119fps or 240fps --> 235fps) on heavy modchart with drunk, path enabled, etc; especially when sustains and path rendering are active at the same time.
If this sounds useful, I can share a more concrete breakdown of the changes that helped the most.
If you need an example, here it is:
In my engine (sorry it's a bit messy):
https://github.com/Psych-Plus-Team/FNF-PlusEngine/tree/dev/source/funkin/modding/modchart
In a forked library:
https://github.com/LeninAsto/FunkinModchart
Hi, thanks for the work on this library.
After integrating a similar renderer into my own engine and profiling dense modcharts, I noticed that a big part of the FPS drop comes from per-frame allocations and repeated path work inside the renderer hot path.
I think there are a few optimization opportunities that could help a lot without changing the public API:
Reuse static index and UV buffers for arrows, holds and paths instead of rebuilding them inside prepare calls.
Reuse scratch objects like Vector3, ArrowData and temporary transform data instead of allocating them every frame.
Avoid repeated cloning or fresh vector creation inside hold/path loops when the base position can be reused.
Rebuild hold/path geometry buffers only when subdivision count or path resolution actually changes.
Consider optional adaptive sustain subdivisions when FPS stays low for several frames.
Expose lightweight renderer stats for profiling, such as draw command count, active holds, vertex count and emission time.
I applied similar changes on my side and it noticeably reduced FPS drops (Almost a hold that's too long would drop between 0 and 2 fps --> 120fps - 119fps or 240fps --> 235fps) on heavy modchart with drunk, path enabled, etc; especially when sustains and path rendering are active at the same time.
If this sounds useful, I can share a more concrete breakdown of the changes that helped the most.
If you need an example, here it is:
In my engine (sorry it's a bit messy):
https://github.com/Psych-Plus-Team/FNF-PlusEngine/tree/dev/source/funkin/modding/modchart
In a forked library:
https://github.com/LeninAsto/FunkinModchart