1.前言
本文主要针对Graphics类进行texture和mesh的绘制。
2.Draw Texture
使用Graphics类直接进行Texture绘制时,由于属于直接绘制到平面上,所以需要转换到平面像素空间内,所以需要用到LoadPixelMatrix方法。对于空间转换可以参考这一节
2.1 ToScreen
示例代码:
public void Dmainxture() { GL.PushMatrix(); //GL.LoadPixelMatrix(); GL.LoadPixelMatrix(0,Screen.width,Screen.height,0); Graphics.DrawTexture(new Rect(0, 0, 200, 100), mainTexture); GL.PopMatrix(); }
代码中Graphics.DrawTexture使用的是最基本的方法,即将mainTexture绘制到屏幕new Rect(0, 0, 200, 100)的范围内。此方法有很多重载,可以根据自己的需求选择不同的方法。
使用GL.LoadPixelMatrix()(代码中注释掉的部分)进行坐标转换时,mainTexture会被绘制在屏幕左下角区域,但是像素上下是反的。这是由于不同的图形接口,texture对应的坐标原点不同。OpenGl为左下角,D3d为左上角。如果使用GL.LoadPixelMatrix(0,Screen.width,Screen.height,0)则像素不会反转,但是由于坐标变换矩阵变成从上到下,所以绘制屏幕的左上角。
2.1.1 调用位置
由于是绘制在屏幕上,所以只能在OnGui方法和OnPostRender中调用,在update中则会被camera渲染时会clear掉。但是如果将texture绘制到一个RenderTexture中则可以在update中可以。
2.2 ToTarget
示例代码:
public void DrawTextureToTarget() { Graphics.SetRenderTarget(target); clearBuffer.Clear(); clearBuffer.ClearRenderTarget(true, true, clearColor); Graphics.ExecuteCommandBuffer(clearBuffer); GL.PushMatrix(); GL.LoadPixelMatrix(0, target.width, target.height, 0); //GL.LoadPixelMatrix(0, target.width, 0, target.height); Graphics.DrawTexture(new Rect(0, 0, target.width, target.height), mainTexture); GL.PopMatrix(); }
Graphics.SetRenderTarget(target);将绘制结果绘制在一个RenderTexture类型的变量target上,所以屏幕变换需要使用GL.LoadPixelMatrix(0, target.width, target.height, 0);,此时可以在update中调用。
3.Draw Mesh
3.1 Update中调用
示例代码:
public void DrawMesh() { Graphics.DrawMesh(Graphics00Mesh.Instance.GetMesh(10, 5), Matrix4x4.identity, material, 0); //Graphics.DrawMesh(Graphics00Mesh.Instance.GetMesh(10, 5), center,Quaternion.identity, material, 0); }
Graphics.DrawMesh同样有很多重载,可以满足众多需求,文中只给出了两个示例,一个通过提供矩阵进行坐标变换,另一个(注释掉的方法)则通过提供mesh所在的位置和旋转在进行定位。由于时绘制的模型,所以只能在update中调用。
3.2 OnPostRender中调用
在渲染阶段调用只能使用Graphics.DrawMeshNow方法,让指令立即生效。
4.完整代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; public enum DrawLocation { ONGUI, POSTRENDER, UPDATE } public class Graphics06Graphics : MonoBehaviour { public DrawLocation location = DrawLocation.ONGUI; public bool toTarget = false; public Texture mainTexture; public RenderTexture target; public Color clearColor = Color.red; CommandBuffer clearBuffer; void Draw() { if (toTarget) { DrawTextureToTarget(); } else { DrawTexture(); } } public void DrawTexture() { GL.PushMatrix(); //GL.LoadPixelMatrix(); GL.LoadPixelMatrix(0,Screen.width,Screen.height,0); Graphics.DrawTexture(new Rect(0, 0, 200, 100), mainTexture); GL.PopMatrix(); } public void DrawTextureToTarget() { Graphics.SetRenderTarget(target); clearBuffer.Clear(); clearBuffer.ClearRenderTarget(true, true, clearColor); Graphics.ExecuteCommandBuffer(clearBuffer); GL.PushMatrix(); GL.LoadPixelMatrix(0, target.width, target.height, 0); //GL.LoadPixelMatrix(0, target.width, 0, target.height); Graphics.DrawTexture(new Rect(0, 0, target.width, target.height), mainTexture); GL.PopMatrix(); } private void Start() { clearBuffer = new CommandBuffer() { name = "Clear Buffer" }; } private void OnGUI() { if (location != DrawLocation.ONGUI) return; if (Event.current.type.Equals(EventType.Repaint)) { Draw(); } } private void Update() { if (location != DrawLocation.UPDATE) return; //如果此时绘制到屏幕上,则不会看到绘制的结果 Draw(); } private void OnPostRender() { if (location != DrawLocation.POSTRENDER) return; Draw(); } }
5.结语
由于将mesh绘制到RenderTexture上稍微麻烦一点,还涉及到贴图等问题,所以单独在下一节中讲解分析。