using FairyGUI; using FairyGUI.Utils; using System.Collections; using UnityEngine; public class RenderImage { public Transform modelRoot { get; private set; } Camera _camera; Image _image; Transform _root; Transform _background; Transform _model; RenderTexture _renderTexture; int _width; int _height; bool _cacheTexture; float _rotating; const int RENDER_LAYER = 0; const int HIDDEN_LAYER = 10; public RenderImage(GGraph holder) { _width = (int)holder.width; _height = (int)holder.height; _cacheTexture = true; this._image = new Image(); holder.SetNativeObject(this._image); Object prefab = Resources.Load("RenderTexture/RenderImageCamera"); GameObject go = (GameObject)Object.Instantiate(prefab); _camera = go.GetComponent(); _camera.transform.position = new Vector3(0, 1000, 0); _camera.cullingMask = 1 << RENDER_LAYER; _camera.enabled = false; Object.DontDestroyOnLoad(_camera.gameObject); this._root = new GameObject("RenderImage").transform; this._root.SetParent(_camera.transform, false); SetLayer(this._root.gameObject, HIDDEN_LAYER); this.modelRoot = new GameObject("model_root").transform; this.modelRoot.SetParent(this._root, false); this._background = new GameObject("background").transform; this._background.SetParent(this._root, false); this._image.onAddedToStage.Add(OnAddedToStage); this._image.onRemovedFromStage.Add(OnRemoveFromStage); if (this._image.stage != null) OnAddedToStage(); else _camera.gameObject.SetActive(false); } public void Dispose() { Object.Destroy(_camera.gameObject); DestroyTexture(); this._image.Dispose(); this._image = null; } /// /// The rendertexture is not transparent. So if you want to the UI elements can be seen in the back of the models/particles in rendertexture, /// you can set a maximunm two images for background. /// Be careful if your image is 9 grid scaling, you must make sure the place holder is inside the middle box(dont cover from border to middle). /// /// public void SetBackground(GObject image) { SetBackground(image, null); } /// /// The rendertexture is not transparent. So if you want to the UI elements can be seen in the back of the models/particles in rendertexture, /// you can set a maximunm two images for background. /// /// /// public void SetBackground(GObject image1, GObject image2) { Image source1 = (Image)image1.displayObject; Image source2 = image2 != null ? (Image)image2.displayObject : null; Vector3 pos = _background.position; pos.z = _camera.farClipPlane; _background.position = pos; Vector2[] uv = new Vector2[4]; Vector2[] uv2 = null; Rect rect = _image.TransformRect(new Rect(0, 0, this._width, this._height), source1); Rect uvRect = GetImageUVRect(source1, rect, uv); if (source2 != null) { rect = _image.TransformRect(new Rect(0, 0, this._width, this._height), source2); uv2 = new Vector2[4]; GetImageUVRect(source2, rect, uv2); } Vector3[] vertices = new Vector3[4]; for (int i = 0; i < 4; i++) { Vector2 v = uv[i]; vertices[i] = new Vector3((v.x - uvRect.x) / uvRect.width * 2 - 1, (v.y - uvRect.y) / uvRect.height * 2 - 1, 0); } Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.uv = uv; if (uv2 != null) mesh.uv2 = uv2; mesh.colors32 = new Color32[] { Color.white, Color.white, Color.white, Color.white }; mesh.triangles = new int[] { 0, 1, 2, 2, 3, 0 }; MeshFilter meshFilter = this._background.gameObject.GetComponent(); if (meshFilter == null) meshFilter = this._background.gameObject.AddComponent(); meshFilter.mesh = mesh; MeshRenderer meshRenderer = this._background.gameObject.GetComponent(); if (meshRenderer == null) meshRenderer = this._background.gameObject.AddComponent(); #if (UNITY_5 || UNITY_5_3_OR_NEWER) meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; #else meshRenderer.castShadows = false; #endif meshRenderer.receiveShadows = false; Shader shader = Shader.Find("Game/FullScreen"); Material mat = new Material(shader); mat.mainTexture = source1.texture.nativeTexture; if (source2 != null) mat.SetTexture("_Tex2", source2.texture.nativeTexture); meshRenderer.material = mat; } Rect GetImageUVRect(Image image, Rect localRect, Vector2[] uv) { Rect imageRect = new Rect(0, 0, image.size.x, image.size.y); Rect bound = ToolSet.Intersection(ref imageRect, ref localRect); Rect uvRect = image.texture.uvRect; if (image.scale9Grid != null) { Rect gridRect = (Rect)image.scale9Grid; float sourceW = image.texture.width; float sourceH = image.texture.height; uvRect = Rect.MinMaxRect(Mathf.Lerp(uvRect.xMin, uvRect.xMax, gridRect.xMin / sourceW), Mathf.Lerp(uvRect.yMin, uvRect.yMax, (sourceH - gridRect.yMax) / sourceH), Mathf.Lerp(uvRect.xMin, uvRect.xMax, gridRect.xMax / sourceW), Mathf.Lerp(uvRect.yMin, uvRect.yMax, (sourceH - gridRect.yMin) / sourceH)); float vw = imageRect.width - (sourceW - gridRect.width); float vh = imageRect.height - (sourceH - gridRect.height); uvRect = Rect.MinMaxRect(Mathf.Lerp(uvRect.xMin, uvRect.xMax, (bound.x - gridRect.x) / vw), Mathf.Lerp(uvRect.yMin, uvRect.yMax, (imageRect.height - bound.yMax - (sourceH - gridRect.yMax)) / vh), Mathf.Lerp(uvRect.xMin, uvRect.xMax, (bound.xMax - gridRect.x) / vw), Mathf.Lerp(uvRect.yMin, uvRect.yMax, (imageRect.height - bound.yMin - gridRect.y) / vh)); } else { uvRect = Rect.MinMaxRect(Mathf.Lerp(uvRect.xMin, uvRect.xMax, bound.xMin / imageRect.width), Mathf.Lerp(uvRect.yMin, uvRect.yMax, (imageRect.height - bound.yMax) / imageRect.height), Mathf.Lerp(uvRect.xMin, uvRect.xMax, bound.xMax / imageRect.width), Mathf.Lerp(uvRect.yMin, uvRect.yMax, (imageRect.height - bound.yMin) / imageRect.height)); } uv[0] = uvRect.position; uv[1] = new Vector2(uvRect.xMin, uvRect.yMax); uv[2] = new Vector2(uvRect.xMax, uvRect.yMax); uv[3] = new Vector2(uvRect.xMax, uvRect.yMin); if (image.texture.rotated) ToolSet.RotateUV(uv, ref image.texture.uvRect); return uvRect; } public void LoadModel(string model) { this.UnloadModel(); Object prefab = Resources.Load(model); GameObject go = ((GameObject)Object.Instantiate(prefab)); _model = go.transform; _model.SetParent(this.modelRoot, false); } public void UnloadModel() { if (_model != null) { Object.Destroy(_model.gameObject); _model = null; } _rotating = 0; } public void StartRotate(float delta) { _rotating = delta; } public void StopRotate() { _rotating = 0; } void CreateTexture() { if (_renderTexture != null) return; _renderTexture = new RenderTexture(_width, _height, 24, RenderTextureFormat.ARGB32) { antiAliasing = 1, filterMode = FilterMode.Bilinear, anisoLevel = 0, useMipMap = false }; this._image.texture = new NTexture(_renderTexture); this._image.blendMode = BlendMode.Off; } void DestroyTexture() { if (_renderTexture != null) { Object.Destroy(_renderTexture); _renderTexture = null; this._image.texture = null; } } void OnAddedToStage() { if (_renderTexture == null) CreateTexture(); Timers.inst.AddUpdate(this.Render); _camera.gameObject.SetActive(true); Render(); } void OnRemoveFromStage() { if (!_cacheTexture) DestroyTexture(); Timers.inst.Remove(this.Render); _camera.gameObject.SetActive(false); } void Render(object param = null) { if (_rotating != 0 && this.modelRoot != null) { Vector3 localRotation = this.modelRoot.localRotation.eulerAngles; localRotation.y += _rotating; this.modelRoot.localRotation = Quaternion.Euler(localRotation); } SetLayer(this._root.gameObject, RENDER_LAYER); _camera.targetTexture = this._renderTexture; RenderTexture old = RenderTexture.active; RenderTexture.active = this._renderTexture; GL.Clear(true, true, Color.clear); _camera.Render(); RenderTexture.active = old; SetLayer(this._root.gameObject, HIDDEN_LAYER); } void SetLayer(GameObject go, int layer) { Transform[] transforms = go.GetComponentsInChildren(true); foreach (Transform t in transforms) { t.gameObject.layer = layer; } } }