Summary of threejs texture animation

introduction

In 3D visualization, many animations are involved, among which texture animation is a very important one. This article introduces several ideas of texture animation for everyone to discuss together.

flow animation

The flow animation allows the texture to produce a flowing effect by setting the repeat property of the texture and constantly changing the offset of the texture object. This kind of animation is not difficult to achieve, first load the texture, as shown below:

let img = new Image();
img.src = './images/path.png';
let texture = new eg.Texture(img);
img.onload = function () {
    texture.needsUpdate = true;
}
texture.repeat.set(100,1);
tube.material.map= texture;

function render(){
 tube.material.map.wrapS = eg.RepeatWrapping;
 tube.material.map.offset.set(offset,0);
 tube.material.map.needsUpdate = true;
 offset += 0.01;
}

The above code implements a tube (pipeline), and then adds a texture to the pipeline. During rendering, the offset value of the texture object is constantly updated, and then a flowing animation can be produced. As shown below:

flow.gif

Sprite animation (Sprite Sheet)

Atlas is also often referred to as a sprite map, which is to put a series of small pictures on a large picture according to a certain layout. When in use, intercept a part of the large image to obtain a small image. This is a common method on the web side, and is usually used to reduce the number of pictures, thereby reducing the number of network requests.

Through the sprite map, each frame of the animation series can be laid out on the sprite map. Then create a texture object through the sprite image, set the repeat and offset of the texture, let each drawing obtain a certain frame image on the sprite image, and continuously change the offset to form the animation effect of drawing different frames. For example, the following picture:

image.png

image.png

The demo of threejs below is such an effect, so the code will not be repeated here. Interested readers can view the source code of the demo.

https://stemkoski.github.io/Three.js/Texture-Animation.html The effect is shown in the figure below:

flow2.gif

animated gifs

The gif image itself has its own animation. If the gif is placed on the Image object, the animation will play automatically, but when the gif is used as the image of the texture object. Animations are not played automatically.
To automatically play gif animation, you need to use a library that parses gif, parse each frame of the gif image, and draw each frame of image on a canvas, and use the canvas as the image of the texture object. The general code is as follows:

Load the gif image and parse the image. Among them, a library omggif is used to parse the picture, and the GifReader inside can be used to parse the frame data of the gif picture:

import { GifReader } from 'omggif';
  const loader = new FileLoader(this.manager);
    loader.setPath(this.path);
    loader.setResponseType('arraybuffer');

    loader.load(url, (response) => {
      const gifData = new Uint8Array(response);
      const reader = new GifReader(gifData);
      if (onLoad) onLoad(reader);
    }, onProgress, onError);

Then continuously update the image of the texture:

 draw() {
      if (!this.reader) {
        return;
      }
      
      const { reader, image, context } = this;
      const { width, height } = image;
  
      const frameNum = ++this.frameNumber % reader.numFrames();
      const frameInfo = reader.frameInfo(frameNum);
  
      if (frameNum === 0) {
        // always clear canvas to start
        context.clearRect(0, 0, width, height);
      } else if (this.previousFrameInfo && this.previousFrameInfo.disposal === 2) {
        // disposal was "restore to background" which is essentially "restore to transparent"
        context.clearRect(this.previousFrameInfo.x,
                          this.previousFrameInfo.y,
                          this.previousFrameInfo.width,
                          this.previousFrameInfo.height);
      }
  
      const imageData = context.getImageData(0, 0, width, height);
      reader.decodeAndBlitFrameRGBA(frameNum, imageData.data);
      context.putImageData(imageData, 0, 0);
  
      this.needsUpdate = true;
  
      this.previousFrameInfo = frameInfo;
      this.timeoutId = setTimeout(this.draw.bind(this), (frameInfo.delay || 2) * 10);
    }

The final gif texture effect is shown in the figure below

flow3.gif

APNG animation

APNG pictures are similar to gif pictures, and they are also animated pictures. But compared to gif. APNG can be set translucent, and the edge aliasing is not serious, so the effect of using APNG pictures is better than that of gif pictures.

Similar in principle, it also parses the APNG image, and then draws each frame to the canvas at a time, and continuously updates the texture object. To parse APNG images, an open source library, APNG-canvas, is used. Interested readers can do their own research and will not focus on it here.

After the parsing is complete, the parsed frame set can be drawn, the code is as follows:

draw() {
      if (!this.reader) {
        return;
      }
      
      const { reader, image, context } = this;
      const { width, height } = image;
  
      const frameNum = ++this.frameNumber % reader.numFrames;
      const frameInfo = reader.frames[frameNum];
  
      if (frameNum === 0) {
        // always clear canvas to start
        context.clearRect(0, 0, width, height);
      // } else if (this.previousFrameInfo && this.previousFrameInfo.disposal === 2) {
      } else if (this.previousFrameInfo) {
        // disposal was "restore to background" which is essentially "restore to transparent"
        context.clearRect(this.previousFrameInfo.left,
                          this.previousFrameInfo.top,
                          this.previousFrameInfo.width,
                          this.previousFrameInfo.height);
      }
  
      const imageData = context.getImageData(0, 0, width, height);
      // reader.decodeAndBlitFrameRGBA(frameNum, imageData.data);
      // context.putImageData(imageData, 0, 0);
      context.drawImage(frameInfo.img,frameInfo.left,frameInfo.top,frameInfo.width,frameInfo.height);
  
      this.needsUpdate = true;
  
      this.previousFrameInfo = frameInfo;
      this.timeoutId = setTimeout(this.draw.bind(this), frameInfo.delay);

The final apng texture effect is shown in the figure below

1.gif

Summarize

This article introduces various implementation ideas of theejs texture animation. Includes texture flows, sprite maps, gif and apng animations. With these animation capabilities, rich and colorful visualizations can be created.

If you are interested in visualization, you can communicate with me, WeChat 541002349 (you can enter the WeChat group)
and follow the official account "ITMan Biaoshu" to receive more valuable articles in time.

Guess you like

Origin blog.csdn.net/netcy/article/details/121993432