private static RenderTexture _getTexture2D_rt;
public static Texture2D GetTexture2DFromImage(Image image, Texture2D atlasTexture)
{
RenderTexture targetTexture = null;
if (Camera.main != null)
{
targetTexture = Camera.main.targetTexture;
}
if (_getTexture2D_rt == null)
{
_getTexture2D_rt = RenderTexture.GetTemporary(
atlasTexture.width,
atlasTexture.height);
}
else
{
_getTexture2D_rt.Release();
_getTexture2D_rt.width = atlasTexture.width;
_getTexture2D_rt.height = atlasTexture.height;
}
if (targetTexture != null)
{
Camera.main.targetTexture = null;
}
Material material = new Material(image.material);
var clipRect = new Vector4(0, 0, 1, 1);//_ClipRect各方向的取值范围是0~1。
material.SetVector("_ClipRect", clipRect);
Graphics.Blit(atlasTexture, _getTexture2D_rt, material);
RenderTexture previous = RenderTexture.active;
// GL.Clear(true, false, Color.clear);
RenderTexture.active = _getTexture2D_rt;
Texture2D myTexture2D;
//原图
if (image.mainTexture == null || (image.sprite.rect.width == atlasTexture.width &&
image.sprite.rect.height == atlasTexture.height))
{
int textureWidth = (int)image.sprite.texture.width;
int textureHeight = (int)image.sprite.texture.height;
myTexture2D = new Texture2D(textureWidth, textureHeight, TextureFormat.ARGB32, false);
myTexture2D.ReadPixels(new Rect(0, 0, textureWidth, textureHeight), 0, 0);
}
//图集
else
{
int textureWidth = (int)image.sprite.textureRect.width;
int textureHeight = (int)image.sprite.textureRect.height;
//image.sprite.textureRect.y 从底部网上算,但是ReadPixels从顶部往下算
float textureY = 0;
if(Application.platform == RuntimePlatform.WindowsEditor)
{
//pc(DirectX)的起始点位于左上
textureY = image.sprite.texture.height - (image.sprite.textureRect.y + image.sprite.textureRect.height);
}
else if(Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)
{
//移动平台(OpenGL)位于左下
textureY = image.sprite.textureRect.y;
}
myTexture2D = new Texture2D(textureWidth, textureHeight, TextureFormat.ARGB32, false);
myTexture2D.ReadPixels(new Rect(image.sprite.textureRect.x, textureY, textureWidth, textureHeight), 0, 0);
}
myTexture2D.Apply();
return myTexture2D;
}
注意:
1、Graphics.Blit(atlasTexture, _getTexture2D_rt, material);
由于图集Image用的不是Unity自带的DefaultUIMaterial,所以要想截取正确显示的Texture,需要将material传到Graphics.Blit中去。
api:
public static void Blit(Texture source, RenderTexture dest, Material mat, int pass = -1);
Material to use. Material's shader could do some post-processing effect, for example.
2、从RenderTexutre中ReadPixels的时候需要注意DirectX和OpenGL两种渲染器下坐标系的区别
DirectX: 小图在图集中的坐标从左上角开始计算
OpenGL: 小图在图集中的坐标从右上角开始计算
3、若Material的Shader里引用了Unity底层属性,有可能需要手动赋值。
var clipRect = new Vector4(0, 0, 1, 1);//_ClipRect各方向的取值范围是0~1。
material.SetVector("_ClipRect", clipRect);
比如_ClipRect,这个一般在遮罩功能中使用,原来的赋值是在Image中进行,在脱离Image的情况下,需要手动对_ClipRect进行赋值,才能保证显示正常