Skip to content

Instantly share code, notes, and snippets.

@zwcloud
Created January 4, 2020 14:14
Show Gist options
  • Save zwcloud/5fe7f912ec7353d206bb0c1c15e34742 to your computer and use it in GitHub Desktop.
Save zwcloud/5fe7f912ec7353d206bb0c1c15e34742 to your computer and use it in GitHub Desktop.
A unility class with functions to scale Texture2D Data, by petersvp from http://answers.unity.com/answers/987332/view.html
using UnityEngine;
/// A unility class with functions to scale Texture2D Data.
///
/// Scale is performed on the GPU using RTT, so it's blazing fast.
/// Setting up and Getting back the texture data is the bottleneck.
/// But Scaling itself costs only 1 draw call and 1 RTT State setup!
/// WARNING: This script override the RTT Setup! (It sets a RTT!)
///
/// Note: This scaler does NOT support aspect ratio based scaling. You will have to do it yourself!
/// It supports Alpha, but you will have to divide by alpha in your shaders,
/// because of premultiplied alpha effect. Or you should use blend modes.
public class TextureScaler
{
/// <summary>
/// Returns a scaled copy of given texture.
/// </summary>
/// <param name="tex">Source texure to scale</param>
/// <param name="width">Destination texture width</param>
/// <param name="height">Destination texture height</param>
/// <param name="mode">Filtering mode</param>
public static Texture2D scaled(Texture2D src, int width, int height, FilterMode mode = FilterMode.Trilinear)
{
Rect texR = new Rect(0,0,width,height);
_gpu_scale(src,width,height,mode);
//Get rendered data back to a new texture
Texture2D result = new Texture2D(width, height, TextureFormat.ARGB32, true);
result.Resize(width, height);
result.ReadPixels(texR,0,0,true);
return result;
}
/// <summary>
/// Scales the texture data of the given texture.
/// </summary>
/// <param name="tex">Texure to scale</param>
/// <param name="width">New width</param>
/// <param name="height">New height</param>
/// <param name="mode">Filtering mode</param>
public static void scale(Texture2D tex, int width, int height, FilterMode mode = FilterMode.Trilinear)
{
Rect texR = new Rect(0,0,width,height);
_gpu_scale(tex,width,height,mode);
// Update new texture
tex.Resize(width, height);
tex.ReadPixels(texR,0,0,true);
tex.Apply(true); //Remove this if you hate us applying textures for you :)
}
// Internal unility that renders the source texture into the RTT - the scaling method itself.
static void _gpu_scale(Texture2D src, int width, int height, FilterMode fmode)
{
//We need the source texture in VRAM because we render with it
src.filterMode = fmode;
src.Apply(true);
//Using RTT for best quality and performance. Thanks, Unity 5
RenderTexture rtt = new RenderTexture(width, height, 32);
//Set the RTT in order to render to it
Graphics.SetRenderTarget(rtt);
//Setup 2D matrix in range 0..1, so nobody needs to care about sized
GL.LoadPixelMatrix(0,1,1,0);
//Then clear & draw the texture to fill the entire RTT.
GL.Clear(true,true,new Color(0,0,0,0));
Graphics.DrawTexture(new Rect(0,0,1,1),src);
}
}
@zwcloud
Copy link
Author

zwcloud commented Jan 4, 2020

This GPU approach won't work for a texture with alpha channel.

CPU version:
http://wiki.unity3d.com/index.php/TextureScale

@tomkail
Copy link

tomkail commented Jul 13, 2023

This code leaks memory! You need to dispose the RT when done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment