Unity截图调用OpenGL绘制 您所在的位置:网站首页 unity调用opengl Unity截图调用OpenGL绘制

Unity截图调用OpenGL绘制

2023-08-27 12:33| 来源: 网络整理| 查看: 265

这次研究的是一个屏幕截取并保存的功能。先上图。

1.Ctrl + Alt + X 开始截图。

2.Enter键执行截屏并弹出保存框。

3.截取后保存的图片。

大致的思路是这样:

1.GL类执行界面选框的显示。

2.用Texture2D类设置新的像素块颜色。

3.System.Windows.forms.dll弹出保存对话框,保存图片文件并打开。

难点在于GL框的绘制逻辑以及新的图片生成时屏幕坐标的计算。

代码如下:

ScreenShot类

using UnityEngine; using System.Collections; using System.Windows.Forms; using System.IO; using System.Text; //截屏工具 public class ScreenShot : MonoBehaviour { //选框材质 public Material mat; //初始位置 Vector3 startPos = Vector3.zero; //结束位置 Vector3 endPos = Vector3.zero; //是否绘制 bool isDraw = false; //是否清除 bool isClear = true; void Update () { //左键按下开始绘制 if(Input.GetMouseButtonDown(0)) { isDraw = true; isClear = true; startPos = Input.mousePosition; } //左键松开GL框悬停 if(Input.GetMouseButtonUp(0)) { //鼠标原位置点击不做GL绘制 if(endPos == startPos) { isDraw = false; } isClear = false; } //右键按下重新绘制 if(Input.GetMouseButtonDown(1)) { isDraw = false; enabled = false; } //Enter键按下执行截屏 if(Input.GetKeyDown(KeyCode.Return) && isDraw && !isClear) { isDraw = false; StartCoroutine(DoScreenShot(new Vector2(startPos.x,UnityEngine.Screen.height - startPos.y),new Vector2(endPos.x,UnityEngine.Screen.height - endPos.y))); enabled = false; } } void OnGUI () { //文本提示 if(!isDraw) { GUI.Label(new Rect(Input.mousePosition.x,UnityEngine.Screen.height - Input.mousePosition.y,100,100)," 请框选截图范围"); } if(isDraw && !isClear && endPos != startPos) { GUI.Label(new Rect(Input.mousePosition.x,UnityEngine.Screen.height - Input.mousePosition.y,100,100)," 按下Enter键截屏"); } } void OnPostRender () { //绘制GL线框 if(!isDraw)return; if(isClear) endPos = Input.mousePosition; GL.PushMatrix(); if(!mat)return; mat.SetPass(0); GL.LoadPixelMatrix(); //绘制GL填充面 GL.Begin(GL.QUADS); GL.Color(new Color(Color.yellow.r,Color.yellow.g,Color.yellow.b,0.1f)); GL.Vertex3(startPos.x,startPos.y,0); GL.Vertex3(endPos.x,startPos.y,0); GL.Vertex3(endPos.x,endPos.y,0); GL.Vertex3(startPos.x,endPos.y,0); GL.End(); //绘制GL边框线 GL.Begin(GL.LINES); GL.Color(Color.red); GL.Vertex3(startPos.x,startPos.y,0); GL.Vertex3(endPos.x,startPos.y,0); GL.Vertex3(endPos.x,startPos.y,0); GL.Vertex3(endPos.x,endPos.y,0); GL.Vertex3(endPos.x,endPos.y,0); GL.Vertex3(startPos.x,endPos.y,0); GL.Vertex3(startPos.x,endPos.y,0); GL.Vertex3(startPos.x,startPos.y,0); GL.End(); GL.PopMatrix(); } //截屏 IEnumerator DoScreenShot (Vector2 startPos,Vector2 endPos) { Debug.Log(new Rect(startPos.x < endPos.x ? startPos.x : endPos.x,startPos.y < endPos.y ? UnityEngine.Screen.height - endPos.y : UnityEngine.Screen.height - startPos.y,Mathf.Abs(endPos.x - startPos.x - 2),Mathf.Abs(endPos.y - startPos.y - 2))); yield return new WaitForSeconds(1); Texture2D tex = new Texture2D((int)Mathf.Abs(endPos.x - startPos.x - 2),(int)Mathf.Abs(endPos.y - startPos.y - 2),TextureFormat.RGB24,false); tex.ReadPixels (new Rect(startPos.x < endPos.x ? startPos.x : endPos.x,startPos.y < endPos.y ? UnityEngine.Screen.height - endPos.y : UnityEngine.Screen.height - startPos.y,Mathf.Abs(endPos.x - startPos.x - 2),Mathf.Abs(endPos.y - startPos.y - 2)),0,0); tex.Apply(); Destroy(tex); SaveScreenShot(tex); } //保存文件 void SaveScreenShot (Texture2D tex) { //先将文件保存在工程目录下(其实可以不用这么做) byte[] bytes = tex.EncodeToPNG(); string filename = System.DateTime.Now.Year.ToString("0000") + System.DateTime.Now.Month.ToString("00") + System.DateTime.Now.Day.ToString("00") + System.DateTime.Now.Hour.ToString("00") + System.DateTime.Now.Minute.ToString("00") + System.DateTime.Now.Second.ToString("00") + Random.Range(0,9999).ToString("0000"); string oldFilePath = UnityEngine.Application.dataPath + "/" + filename + ".png"; FileStream f =new FileStream(oldFilePath,FileMode.Create); f.Write(bytes,0,bytes.Length); f.Flush(); f.Close(); System.GC.Collect(); Resources.UnloadUnusedAssets(); //弹出文件保存对话框,调用的是WINDOWS的DLL. SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "png|*.png"; string newFilePath = ""; if (dialog.ShowDialog() == DialogResult.OK) { newFilePath = dialog.FileName; } if(newFilePath != "") { if(File.Exists(newFilePath)) { File.Delete(newFilePath); } File.Move(oldFilePath, newFilePath); UnityEngine.Application.OpenURL(newFilePath); } else { File.Delete(oldFilePath); } } }

 

ScreenShotControl类

using UnityEngine; using System.Collections; //截屏控制 public class ScreenShotControl : MonoBehaviour { ScreenShot screenshot; // Use this for initialization void Start () { screenshot = GetComponent(); } // Update is called once per frame void Update () { } void OnGUI () { //Ctrl + Alt + X 执行截屏 if(Event.current.Equals(Event.KeyboardEvent("^&X"))) { screenshot.enabled = true; } } }

阐述几个开发中的问题: 1.调用Windows的DLL,需要在Unity里更改一下设置。

File -> Build Settings -> Player Settings ->Other Settings -> Optimization -> Api Compatibility Level 更改为 .NET 2.0。

2.在执行完截屏操作后,虽然能够成功生成图片,但是会报一个错。

ReadPixels was called to read pixels from system frame buffer, while not inside drawing frame.

如果有高手知道具体的解决办法,请指教一下。

3.程序的代码结构写的不是太好,请高手指正。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有