THREE.ComposedTexture - play GIF, APNG etc as texture

This is a texture class which allows to use multi-frame images such as GIF or APNG.

Other than most plain GIF players it doesn’t decode every pixel per frame on the fly, or uses putImageData (for larger GIFs this is too expensive), instead if no images provided, the decoded frame buffers will be converted to compressed images.

As GIF and other animated image formats get optimized not every frame is necessarily a full frame, most might only contain changing regions and pixels, so a frame needs to be composed across multiple frames. It also ensures the animation is rendered on a PO2 composition canvas.

This isn’t a GIF decoder, the example uses gifuct-js to decode a gif, you can use any multi-frame format as well as custom frames. A GIF and APNG loader example is included. The structure for the container object which holds the frames is the following.


In you render loop, you need to call texture.update( deltaTime ), or you control which frame is rendered yourself by calling texture.compose( frameIndex ).

Container structure


downscale : Boolean optional
Canvas needs to be power of 2, by default size is upscaled (false).

width : Number
height : Number
frames : Array

Either patch or image should be provided, if a buffer is provided it will be converted to a image.

patch : Uint8Array
image : Image
dims : Object
With left, top, width, height dimensions.
delay : Number
How long the frame is display in milliseconds.
disposalType : Numer
1 of the 3 methods, see GIF specification for more details.



THREE.ComposedTexture( container, ... )
Container object as described above. Other parameters as usual, you can also assign the container later by calling texture.assign( container ).


autoplay : Boolean
If playback automatically starts when loaded, default is true.

auto: Boolean
If playback should be handled globally, call THREE.ComposedTexture.update( delta ) in your render loop to handle all, default is true.

loop: Boolean
If the playback will be looped, default is true.

ready: Boolean
Will be true once all frames are ready to play.

isPlaying: Boolean
Indicates if the animation is currently playing.

time: Number
The current time in ms.

duration: Number
Total duration in ms.


async assign( container )
To assign a container object, if buffers are provided frames will be converted to images first.

update( deltaTime )
For automatic playback of the animation.

Start playback.

Pause playback.

Resume playback.

Stop playback, first frame is shown.

Enjoy cat GIFs in the third dimension :cat:



Pretty cool !
Did you notice what happens when you switch of browser’s tab for some time and come back later ? Seems that play speed get accelerated somehow.

1 Like

That’s probably the delta from THREE.Clock in the demo, animation frame callbacks get paused or throttled in inactive tabs, especially without audio. I’ll check tomorrow :+1: :unicorn:

I’ve made an update now to prevent this, before i considered the overshoot with delta, THREE.Clock doesn’t take into account that requestAnimationFrame is throttled or paused and will give a huge number when running normally again.

Edit: You can also call now THREE.ComposedTexture.update( delta ) in order to automatically handle playback of all composed textures, if you want to handle it yourself you can set auto to false in the container object.

Changed the example, it has a GIF and APNG loader example included now.

1 Like