Ashley Thanks for the reply (and thanks for the comments in the bug report, I understand, that makes sense.)
I do agree that rendering directly to the C3 canvas would be better and that will be something to explore, however, the render is done through the Spine-TS runtime script and it looks like a lot to dive into to figure out (10K lines). It's already set up to render to a canvas, however, also integrating in the render with other sprite objects could be a challenge? Though I think it would be possible if created a Drawing plugin and did the work to integrate the Spine render into the Drawing Plugin Draw function? Something to explore in the future.
I was looking for a short cut to use the existing Spine-TS. I have found a way that works and _seems_ to perform pretty well. I definitely tried to use only C3 SDK, but I think I used a little more. In this method, I created a drawing plugin which replaces a sub texture of the drawing plugin Sprite Sheet with the canvas texture on each Draw() call. There are limitations: it only replaces the top MIP level, so if the Sprite is scaled down, the old image starts to blend in. So, for the game, I will force screen resolution and keep Sprite size relatively the same so the other MIP levels do not kick in (this will likely be a desktop nw.js / Electron game, so I will have some control over which chromium engine the game is shipped with and control over full screen vs windowed.) I know this is not bullet proof, but I think I can work around the issues. If you have suggestions on how to make the below use more C3 SDK functions, that would be very appreciated!
In general for Spine animations, I will just use 1-3 characters animated this way, so 'only' 1-3 texture updates per frame. The rest will be simpler and use traditional sprite frame animation.
var gl = renderer._gl
const imageInfo = this._objectClass.GetImageInfo();
const texture = imageInfo.GetTexture();
if (!texture) return; // dynamic texture load which hasn't completed yet; can't draw anything
const wi = this.GetWorldInfo();
const quad = wi.GetBoundingQuad();
const rcTex = imageInfo.GetTexRect();
var myCanvas = document.getElementById(this._elementId)
// webgl2: gl.texSubImage2D(gl.TEXTURE_2D, 0, (rcTex._left * texture.GetWidth() - 0.5).toFixed(0), (rcTex._top * texture.GetHeight() - 0.5).toFixed(0), myCanvas.width, myCanvas.height, gl.RGBA, gl.UNSIGNED_BYTE, myCanvas);
gl.texSubImage2D(gl.TEXTURE_2D, 0, (rcTex._left * texture.GetWidth()).toFixed(0), (rcTex._top * texture.GetHeight()).toFixed(0), gl.RGBA, gl.UNSIGNED_BYTE, myCanvas);
const ox = Math.round(wi.GetX()) - wi.GetX();
const oy = Math.round(wi.GetY()) - wi.GetY();