Rive Renderer

Another AI answer. The native spine plugin would be a good reference, thank you @ depilz for the great work. Next I will look into setting up building the rive-runtime for Solar2D plugin

Yes, the texture handling in the Spine plugin for Solar2D is conceptually similar to what I described for the Graphics Extensions (Gfxe) plugin and a hypothetical Rive plugin. Let’s break down the parallels and differences:


1. Texture Workflow Similarities

a. Texture Creation & Sharing

  • Spine Plugin:

    • Uses OpenGL to render Spine skeletal animations into textures.
    • Shares GPU textures with Solar2D via native plugin code (e.g., CoronaExternalTextureCallbacks).
    • Example code from spinePlugin:
      // Create OpenGL texture for Spine atlas
      glGenTextures(1, &textureID);
      glBindTexture(GL_TEXTURE_2D, textureID);
      glTexImage2D(..., atlas->getPixels());
      
    • Solar2D Lua binds to this texture via graphics.newTexture().
  • Gfxe/Rive Analog:

    • Both would use similar OpenGL/Vulkan texture workflows.
    • For Rive, replace atlas->getPixels() with Rive’s renderer output (e.g., rive::Renderer::draw()).

b. Dynamic Texture Updates

  • Spine Plugin:

    • Updates textures on every frame by rendering Spine animations into OpenGL textures.
    • Syncs with Solar2D’s frame loop via enterFrame listeners.
  • Gfxe/Rive:

    • Gfxe updates textures by pushing decoded image data (e.g., PNG/JPEG) via CoronaExternalPushTexture.
    • For Rive, you’d render frames into a GPU texture (shared or copied) and update it dynamically.

2. Key Differences

a. Rendering Backend

  • Spine: Uses its own OpenGL renderer for skeletal animations.
  • Rive: Uses Rive’s renderer (OpenGL/Metal/Vulkan) for vector animations.
  • Gfxe: Focuses on static image decoding (no runtime animation).

b. Data Flow

  • Spine:

    • Requires a .atlas file and texture atlas (prebaked).
    • Animations are driven by Spine’s runtime (C++/Java).
  • Rive:

    • Uses .riv files with vector paths and state machines.
    • Requires runtime interpolation of vector data (more dynamic than Spine’s skeletal system).

3. Example Workflow Comparison

Spine Plugin (Reference)

  1. Load Assets:
    // spinePlugin.cpp
    spine::Atlas* atlas = new spine::Atlas("skeleton.atlas", new MyTextureLoader());
    spine::SkeletonJson json(atlas);
    spine::SkeletonData* skeletonData = json.readSkeletonDataFile("skeleton.json");
    
  2. Render Frame:
    void update(lua_State* L) {
      spineRenderer->draw(); // Renders to OpenGL texture
      CoronaExternalPushTexture(L, textureCallbacks); // Update Solar2D texture
    }
    

Rive Plugin (Hypothetical)

  1. Load Rive File:
    // rivePlugin.cpp
    rive::File* file = rive::File::open("animation.riv");
    rive::Artboard* artboard = file->artboard();
    rive::Renderer* renderer = artboard->renderer();
    
  2. Render Frame:
    void update(lua_State* L) {
      renderer->draw(); // Renders to OpenGL/Metal/Vulkan texture
      CoronaExternalPushTexture(L, textureCallbacks); // Share with Solar2D
    }
    

4. Critical Code Snippets

Texture Callbacks (Shared Between Plugins)

// Similar in Spine, Gfxe, and Rive plugins
CoronaExternalTextureCallbacks textureCallbacks;
textureCallbacks.size = sizeof(textureCallbacks);
textureCallbacks.getWidth = [](void* context) { return width; };
textureCallbacks.getHeight = [](void* context) { return height; };
textureCallbacks.onRequestBitmap = [](void* context, CoronaBitmap* bitmap) {
  // Copy pixel data (Gfxe) or bind GPU texture (Spine/Rive)
};

Solar2D Lua Integration

-- Spine, Gfxe, or Rive would expose similar APIs
local spine = require "plugin.spine"
local rive = require "plugin.rive"

local spineActor = spine.newActor("skeleton.json", "atlas.atlas")
local riveAnimation = rive.newAnimation("animation.riv")

5. Takeaways

  • Shared Pattern: All plugins (Spine, Gfxe, Rive) use native code to generate/update textures and expose them to Solar2D via CoronaExternalTextureCallbacks.
  • Rendering Differences:
    • Spine: Prebaked atlas + skeletal deformation.
    • Rive: Vector paths + runtime interpolation.
  • Performance: Direct GPU texture sharing (Spine/Rive) is more efficient than CPU pixel copying (Gfxe).

For a Rive plugin, you’d adapt the Spine plugin’s OpenGL texture workflow but replace Spine’s renderer with Rive’s. The Graphics Extensions Plugin is also a useful reference for handling dynamic pixel data.