guansss / pixi-live2d-display

A PixiJS plugin to display Live2D models of any kind.
https://guansss.github.io/pixi-live2d-display/
MIT License
823 stars 125 forks source link

Rendering multiple live2d model #82

Open ifundeasy opened 1 year ago

ifundeasy commented 1 year ago

Hi Everyone!

I struggled to render Live2d models to different canvas elements using pixi.js.

Btw, I follow the guidelines for creating a container using (Live2dModel.from method) for adding a model container to Pixi stage (pixiApplication.stage.addChild() method) Let's say, I have A dan B models, and want to put A model to the first canvas element, and B to the second canvas element.

The first rendering is fine, but when I did put the B model on the second canvas the A model (on the first canvas) was gone.

Could you give me a simple example to help my issue?

guansss commented 1 year ago

Could you provide a minimal repro?

ifundeasy commented 1 year ago

Hi @guansss! Thanks for your reply

Please check my this html file.

Could you provide a minimal repro?


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<style>
body {
padding: 0;
margin: 0;
height: 100vh;
}
.container {
width: 50%;
height: 50%
}
.bg-antiquewhite {
background-color: antiquewhite;
}
.bg-azure {
background-color: azure;
}
</style>
</head>
<body>
<div id="container-1" class="container bg-antiquewhite">
<canvas id="canvas-1"></canvas>
</div>
<div id="container-2" class="container bg-azure">
<canvas id="canvas-2"></canvas>
</div>
<script src="https://cubism.live2d.com/sdk-web/cubismcore/live2dcubismcore.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/dylanNew/live2d/webgl/Live2D/lib/live2d.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/7.0.3/pixi.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pixi-live2d-display/dist/index.min.js"></script>
<script>
const {
Application,
Container,
live2d: { Live2DModel, Live2DFactory }
} = PIXI;
  async function render({ usePixiContainer, canvasEl, parentEl, modelUrl }) {
    console.debug(`usePixiContainer=${usePixiContainer} for rendering modelUrl=${modelUrl}`)

    const app = new Application({
      view: canvasEl,
      autoStart: true,
      transparent: true,
      backgroundAlpha: 0,
      resizeTo: parentEl
    });

    // Load live2d model
    // const currentModel = new Live2DModel({ autoInteract: false })
    // await Live2DFactory.setupLive2DModel(currentModel, modelUrl, { autoInteract: false })
    const currentModel = await Live2DModel.from(modelUrl, { autoInteract: false });
    currentModel.scale.set(0.1);
    currentModel.interactive = true;
    currentModel.anchor.set(0.5, 0.5);
    currentModel.position.set(parentEl.offsetWidth * 0.5, parentEl.offsetHeight * 0.8);

    // Add events to drag model
    currentModel.on('pointerdown', e => {
      currentModel.offsetX = e.data.global.x - currentModel.position.x;
      currentModel.offsetY = e.data.global.y - currentModel.position.y;
      currentModel.dragging = true;
    });
    currentModel.on('pointerup', e => {
      currentModel.dragging = false;
    });
    currentModel.on('pointermove', e => {
      if (currentModel.dragging) {
        currentModel.position.set(
          e.data.global.x - currentModel.offsetX,
          e.data.global.y - currentModel.offsetY
        );
      }
    });

    if (usePixiContainer) {
      const container = new Container();
      container.addChild(currentModel);
      app.stage.addChild(container);

      return;
    }

    app.stage.addChild(currentModel);
  }

  (async function () {
    await render({
      usePixiContainer: false,
      canvasEl: document.getElementById('canvas-1'),
      parentEl: document.getElementById('container-1'),
      modelUrl: 'https://yeemachine.github.io/k2021/live2d/4.0/hiyori/hiyori_free_t06.model3.json'
    })

    await render({
      usePixiContainer: false,
      canvasEl: document.getElementById('canvas-2'),
      parentEl: document.getElementById('container-2'),
      modelUrl: 'https://yeemachine.github.io/k2021/live2d/4.0/haru_greeter/haru_greeter_t03.model3.json'
    })

    await render({
      usePixiContainer: true,
      canvasEl: document.getElementById('canvas-1'),
      parentEl: document.getElementById('container-1'),
      modelUrl: 'https://yeemachine.github.io/k2021/live2d/4.0/hiyori/hiyori_free_t06.model3.json'
    })

    await render({
      usePixiContainer: true,
      canvasEl: document.getElementById('canvas-2'),
      parentEl: document.getElementById('container-2'),
      modelUrl: 'https://yeemachine.github.io/k2021/live2d/4.0/haru_greeter/haru_greeter_t03.model3.json'
    })
  })()
</script>

guansss commented 1 year ago

OK I see, it turns out Live2D framework doesn't support rendering on multiple canvas (I thought it does). The WebGL context are globally shared between all models, meaning that rendering a model in another canvas will overwrite the global WebGL context and break other models' rendering.

So this is a limitation of Live2D, I think I can solve it for Cubism 4 since it's open source, but not sure about Cubism 2.

It may take a while to be done, for now I suggest you to put canvases in separate iframes, or, render all models in a single hidden canvas and copy the regions to each destination canvas.

guansss commented 1 year ago

Please keep this issue open. 😉

ifundeasy commented 1 year ago

Well, thanks @guansss, for now, I'm using an iframe for rendering multiple live2d models to prevent this issue and this is work

xiaoqiang1999 commented 4 days ago

首先感谢大佬的开源,然后我也遇到了这个问题,只能先用iframe了