Oh, it's pending approval by an admin. Here it is in full:
Hey, Ashley, Mario from Spine here. Sorry for bursting into this thread. Mikal asked me to chime in.
I think your suggestion of going through IWebGLRenderer (and IWebGLTexture) is spot on. That will ensure future compatibility, and allow the underlying C3 renderer to do its best batching renderables.
That said, for the renderables that need to be rendered for Spine skeletons, the current IWebGLRenderer interface is not ideal. There are two issues:
- IWebGLRenderer only supports rendering individual (textured) quads. Spine skeletons are rendered as textured triangles. A single skeleton may consist of a few dozen to thousands of (indexed) triangles. Going through IWebGLRenderer would thus require us to use degenrate quads to render triangles, and also looses us the more performant indexed triangle rendering. I assume that methods like IWebGLRender.Quad() and consorts add vertices to an underlying vertex buffer with a fixed vertex format, i.e. x/y,u/v,rgba.
Maybe it would be possible to add an "expert" method like IWebGLRenderer.triangles()? The parameter would be a array of vertices in C3's vertex format. Each consecutive 3 vertices would make up one triangle. Ideally the array contents could be directly copied to the renderer's vertex buffer (which may require the parameter to be an ArrayBuffer instead of a vanilla JS array). This would still not allow for indexed triangle rendering, but would remove all the overhead of issuing individual calls to IWebGLRenderer.Quad().
- Spine's two color tinting (aka tint black, see esotericsoftware.com/spine-slots) requires a custom vertex format (x,y,u,v,color,dark color) and shader. Why the custom vertex format with the additional attribute? Batching. A Spine skeleton consists of many attachments, e.g. one for the head, one for the torso, etc. Each attachment is essentially a textured triangle mesh. There may be dozens of attachments in a single skeleton (amd hence dozens of meshes). Each attachment can apply two color tinting to its mesh. This could be implemented by setting the dark color as a shader uniform, but that would break batching of attachments. Instead, the dark color of an attachment is written as an additional vertex attribute to each of its mesh' vertices. While that may seem expensive, it's actually orders of magnitude faster, as it allows batching. The additional data that needs uploading to the GPU is negligible.
In order for this to work in C3, IWebGLRenderer would have to expose a way to specify the vertex format (and the two color tint shader, which seems possible). I see two ways to accomplish this.
One way would be to allow extending the vertex format C3 is using. The vertex format would always have the default C3 attributes. A plugin could then tell C3 to add additional attributes to the defaults. The C3 renderer would just write a default value for those additional attributes, while the plugin can set whatever is necessary when rendering renderables it controls. The plugin would still go through the proposed IWebGLRenderer.triangles() above, so the C3 renderer could still batch everything as the vertex format is constant across all renderables.
Now, changing the default C3 vertex format is a big ask imo, as it may ripple through the entire C3 rendering code base I'd assume. I could imagine another method on IWebGLRenderer, i.e. IWebGLRenderer.customTriangles(triangles, vertexFormat, shader). That would allow a plugin to implement its own batching with a custom vertexFormat and shader for a single renderable, i.e. one Spine skeleton consisting of dozens of meshes. That renderable could of course no longer be batched with other C3 quads. I think this could be a good compromise between performance, extensibility, and the amount of changes needed in C3 itself.