在开发过程中,有2个与RenderText相关的2个需求,看到 Unity3d中渲染到RenderTexture的原理,几种方式以及一些问题 这篇博客,对RenderText的理解更深了一些。
将这个FBO直接关联一个GPU上的texture对象,这样就等于在绘制时就直接绘制到这个texure上,这样也省去了拷贝时间,GLES中一般是使用FramebufferTexture2D()这样的接口。
那么unity的RenderTexture正是这种方式的一种实现,它定义了在server-side的一个tex对象,然后将渲染直接绘制到这个tex上。
在此记录一下RenderTexture的应用。
UGUI上显示模型(粒子特效由于Alpha透明通道,显示会有一点问题,可以通过Shader Blend混合处理)
Camera相机拍照分享,保存为jpg
这两个功能的原理都是: One typical usage of render textures is setting them as the "target texture" property of a Camera ( Camera.targetTexture ), this will make a camera render into a texture instead of rendering to the screen.
官方文档
1. UGUI上显示模型
- 创建拍摄用的摄像机
- 创建RenderTexture并绑定到摄像机camera.targetTexture上
- RenderTexture绑定到rawImage.texture上(rawImage见上图)
- 创建显示的模型,相机可见
- 注意Destroy销毁 创建出来的RenderTexture 和相机
- 注意模型上的粒子特效由于Alpha透明通道,显示会有一点问题,可以通过Shader Blend混合处理,挂载在rawImage上。
public void CreateCamera(Vector3 pos, Vector3 rot, int width, int height, string layerName, float size)
{
// 创建拍摄用的摄像机
GameObject go = new GameObject("ModelCamera");
_camera = go.AddComponent<Camera>();
_camera.clearFlags = CameraClearFlags.SolidColor;
_camera.transform.position = pos;
_camera.transform.rotation = Quaternion.Euler(rot);
_camera.cullingMask = LayerMask.GetMask(layerName);
_camera.orthographic = true;
_camera.orthographicSize = size;
_camera.backgroundColor = new Color(0,0,0,0);
// 创建RenderTexture并绑定到摄像机上
_renderTexture = new RenderTexture(width, height, 8);
_camera.targetTexture = _renderTexture;
if (_rawImage != null)
{
_rawImage.texture = _renderTexture;
}
}
2. Camera相机拍照分享,保存为jpg
private IEnumerator CameraPhoto(Camera cam, Rect rect, string name) {
if (rt == null) {
rt = RenderTexture.GetTemporary(renderTextureDesc);
}
cam.targetTexture = rt;
cam.Render();
RenderTexture currentActiveRT = RenderTexture.active;
RenderTexture.active = rt;
Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
screenShot.ReadPixels(rect, 0, 0);
screenShot.Apply();
yield return new WaitForEndOfFrame();
cam.targetTexture = null;
RenderTexture.active = currentActiveRT;
byte[] bytes = screenShot.EncodeToJPG();
string file = Application.dataPath + "/Texture/" + name;
System.IO.File.WriteAllBytes(file, bytes);
}
- Rendertexture的分配和销毁上有一个地方需要注意:
如果频繁的要new一个rt出来,那么不要直接new,而是使用RenderTexture提供的GetTemporary和ReleaseTemporary,它将在内部维护一个池,反复重用一些大小格式一样的rt资源,因为让GPU为你分配一个新的texture其实是要耗时间的。 - EncodeToJPG 生成的图片体积更小