Runtime Texture Atlas

Introduction

Runtime Texture Atlas was needed when I was creating a blood splatter system for Unity. 

This asset includes 2 methods, Graphics.Blit and Graphics.DrawTexture, with accompanying shaders for each method. The DrawTexture method performs faster because Blit is creating an unnecessary quad during computation. However, depending on the use case, Blit may be desired. 

Video Tutorial: https://youtu.be/kVW_DCm6u4M

Terminology

AtlasThe huge texture that will host a plethora of Subtextures. Example: 4096×4096 RenderTexture.
SubtextureA smaller image that will be placed into a grid on the AtlasExample: Icons for your game; Procedurally generated CustomRenderTextures such as blood splatters or bullet holes.
RenderTextureA texture that resides on the GPU. Pixel data is written directly.Graphics.DrawTexture & Graphics.Blit write pixel data to the texture.The Atlas is a RenderTexture.https://docs.unity3d.com/ScriptReference/RenderTexture.html
CustomRenderTextureAn extension of RenderTexture: Pixel data is written by a shader.Procedural shaders / shadergraphs write pixel data to the texture.Not required, but in my case the 32×32 subtextures are generated by a Shadergraph and are rendered to a CustomRenderTexture.https://docs.unity3d.com/ScriptReference/CustomRenderTexture.html
TextureAtlasCreatorA Scriptable Object you will create to configure a runtime texture atlas. Multiple TextureAtlasCreators can be used in your game for various effects, 1 for blood splatters, 1 for bullet holes, 1 for icons, etc.

How To Use

  1. Create a TextureAtlasCreator Scriptable Object by right clicking in your Project Window, Create > Scriptable Objects > Texture Atlas Creator
  1. Add a Rendertexture which will be used for the Atlas or use the default one named: Atlas_RenderTexture_4096x4096.
  2. Configure your Tile Size, or how big each subimage will be.
  3. Select which Graphics API function will be used to copy Pixel Data.
  1. Call TextureAtlasCreator.AddSubimageToAtlas(Texture subimage) to add a texture to the Atlas.
  2. Call TextureAtlasCreator.AddSubimagesToAtlas(Texture[] subimages) to add an array of textures to the Atlas.
  3. To display a Subimage on a material, you can call TextureAtlasCreator.AssignSubtextureToMaterial(int index, Material material)
  4. For testing purposes, you can assign a texture to “Subimage” and then click “Add Subimage To Atlas” to see how the image is added. Also, click “Flood Subimage To Atlas” to flood the Atlas with the subimage. This allows you to test performance and see what happens when images have to loop back to 0 and previous subimages are overwritten. 

Scripts

TextureAtlasCreator.cs

Initialize Atlas

void InitializeAtlas()
Initialize the Atlas variables. Called automatically from Start() and OnValidate() if in the editor.

Add Subimage To Atlas

intAddSubimageToAtlas(Texture subimage)
Adds Texture ‘subimage’ to the Atlas. Returns the index of the subimage in the atlas.

Add Subimages To Atlas

intAddSubimagesToAtlas(Texture[] subimages)
Adds an array of Textures ‘subimages’ to the Atlas. Returns the index of the final subimage.

Assign Subtexture To Material

voidAssignSubtextureToMaterial(int index, Material material)
Given an Atlas Index and a Material, the subtexture at that index will be assigned to the material. Material must have Tiling and Offset parameters.Example: AssignSubtextureToMaterial(AddSubimageToAtlas(subimage), material);

Get Subimage Scale

Vector2GetSubimageScale(int index)
Returns the scale of the subimage in Vector2. Used by AssignSubtextureToMaterial.

Get Subimage Offset

Vector2GetSubimageOffset(int index)
Returns the offset of the subimage in Vector2. Used by AssignSubtextureToMaterial.

Clear Atlas RenderTexture

voidClearAtlasRenderTexture()
Clears the Atlas. All subtextures will be deleted.

AtlasSubtexture.cs

This script is not required and will probably only be used for example purposes. However it may be useful to save a Subtexture’s Index to its Gameobject. For example, a Sword icon is added to the atlas, and the Sword Gameobject has this component added, with a reference to its index in the Atlas. For this case, it’s probably better to just add a “TextureAtlasIndex” variable to your “Sword” class. 

Assign Subtexture At Index 

voidAssignSubtextureAtIndex(int index)
Find the subtexture which exists at Index in the Texture Atlas and assign it to the GameObject’s material.

Help and Support

I will respond quickly to support emails. Send to [email protected]

Discord Support: https://discord.gg/jrvzFbJhYj

Credits

RPG Icons in /Demo/Textures comes from Ravenmore’s Icon Pack 2.0 on OpenGameArt.org.