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.
Usage
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
Container
downscale : Boolean
optional
Canvas needs to be power of 2, by default size is upscaled (false).
width : Number
height : Number
frames : Array
Frame
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.
API
Constructor
THREE.ComposedTexture( container, ... )
Container object as described above. Other parameters as usual, you can also assign the container later by calling texture.assign( container )
.
Properties
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.
Methods
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.
play()
Start playback.
pause()
Pause playback.
resume()
Resume playback.
stop()
Stop playback, first frame is shown.
Enjoy cat GIFs in the third dimension
Version 2
Show details
-
Fixed: for ^141 releases (needsUpdate)
-
Added:
SpriteTexture
for using sprite-sheet textures and playback just likeComposedTexture
-
Added:
toSheet
method onComposedTexture
create a baked sprite-sheet of the frameset
Creating a sprite-sheet fromComposedTexture
will automatically use a ideal layout stripe or atlas and if exceeding a given max resolution scale down to fit -
Added:
timeScale
forComposedTexture
andSpriteTexture
to alter general playback speed (default 1.0).
THREE.SpriteTexture
This new texture class uses a sprite-sheet (atlas or stripe). The animation interface is the same as on ComposedTexture
. There are cases to use either this or ComposedTexture
. The sprite-sheet can be derived from a ComposedTexture
. via simple call .toSheet
or provided from a regular texture.
Benefits
- Only 1 initial texture upload (asked here)
- Texture can be shared for a massive number of instances with individual animation state (related question)
- Can be more memory efficient on JS side by it’s resource being a single texture and the frames not being needed anymore
- You can load an assembled sprite-sheet texture and assign it directly, either you provide the sprite-sheet meta info or let it generate it:
const sprite = new THREE.SpriteTexture( {
texture: spriteSheetTexture,
padding: 0,
columns: 3,
count: 7,
delay: 80
} );
Notice: the benefits of sharing the spritesheet texture are only available for THREE release R138 and higher, since a concept for sharing textures has been added.
When to use SpriteTexture
- You got a smaller amount of frames or/and resolution, typically like 2D game asset sprite-sheets
- You want to render a huge amount of it with different animation states
- You don’t need to use repeat wrapping of the texture or texture transformations
When to use ComposedTexture
- Your resource files for your project/use case are GIF, APNG etc
- You got a lot / larger frames that are too many / too large (or unpredictable in that regard) for a sprite-sheet
- Your main concern is GPU memory,
ComposedTexture
has fixed memory usaged of 1 frame on GPU - You need repeat wrapping of the texture or texture transformations
The outer left showcases a GIF turned to spritesheet and used with SpriteTexture
then.
Things you may want to configure
// May be set by renderer.capabilities.maxTextureSize (recommend default unless needed), sheets going above will be scaled down to it
THREE.ComposedTexture.MaxSpriteSheetResolution = 4096;
// Sprite-sheets below this resolution will be a stripe which is more reasonable for uneven number of frames
THREE.ComposedTexture.MaxStripSize.MaxStripResolution= 2048;