GL绘制
http://wiki.ceeger.com/script/unityengine/classes/gl/gl.multitexcoord?s[]=gl
GL 图形库
Namespace: UnityEngine
Description 描述
Low-level graphics library.
Use this class to manipulate active transformation matrices, issue rendering commands similar to OpenGL's immediate mode and do other low-level graphics tasks. Note that in almost all cases using Graphics.DrawMesh is more efficient than using immediate mode drawing.
这个类进行底层的矩阵变换。通过用函数命令来实现。这和OpenGL(和D3D不同的图形库)的立即模式一样。注意在大部分情况下用Graphics.DrawMesh 比这个立即模式更有效率。
GL immediate drawing functions use whatever is the “current material” set up right now. The material controls how the rendering is done (blending, textures, etc.), so unless you explicitly set it to something before using GL draw functions, the material can happen to be anything. Also, if you call any other drawing commands from inside GL drawing code, they can set material to something else, so make sure it's under control as well.
GL的立即模式用在当材质建立的时候。材质控制着物体该如何渲染(混合纹理等等)。在用GL类前你要明确的设定材质的属性,GL类可以使材质做任何改变。 (下面的实例代码看看会清楚一点)
GL drawing commands execute immediately. That means if you call them in Update(), they will be executed before the camera is rendered (and the camera will most likely clear the screen, making the GL drawing not visible).
GL函数命令会立即执行。不要在Update()函数内放置GL代码,这样会看不到效果。因为GL在 Camera 之前被执行。
The usual place to call GL drawing is most often in OnPostRender() from a script attached to a camera
常用的方法是GL代码放在OnPostRender()函数里面。OnPostRender()作为camera 脚本里的一个函数。
JavaScript:
#pragma strict
public var lineCount: int = 100;
public var radius: float = 3.0f;
static var lineMaterial: Material;
static function CreateLineMaterial() {
if (!lineMaterial) {
// simple colored things.
var shader: var = Shader.Find("Hidden/Internal-Colored");
lineMaterial = new Material(shader);
lineMaterial.hideFlags = HideFlags.HideAndDontSave;
// Turn on alpha blending
lineMaterial.SetInt("_SrcBlend", intUnityEngine.Rendering.BlendMode.SrcAlpha);
lineMaterial.SetInt("_DstBlend", intUnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
// Turn backface culling off
lineMaterial.SetInt("_Cull", intUnityEngine.Rendering.CullMode.Off);
// Turn off depth writes
lineMaterial.SetInt("_ZWrite", 0);
}
}
// Will be called after all regular rendering is done
public function OnRenderObject() {
CreateLineMaterial();
// Apply the line material
lineMaterial.SetPass(0);
GL.PushMatrix();
// match our transform
GL.MultMatrix(transform.localToWorldMatrix);
// Draw lines
GL.Begin(GL.LINES);
for (var i: int = 0; i < lineCount; ++i) {
var a: float = i / floatlineCount;
var angle: float = a * Mathf.PI * 2;
// Vertex colors change from red to green
GL.Color(new Color(a, 1 - a, 0, 0.8F));
// One vertex at transform position
GL.Vertex3(0, 0, 0);
// Another vertex at edge of circle
GL.Vertex3(Mathf.Cos(angle) * radius, Mathf.Sin(angle) * radius, 0);
}
GL.End();
GL.PopMatrix();
}
C#:
using UnityEngine;
public class ExampleClass : MonoBehaviour
{
// When added to an object, draws colored rays from the
// transform position.
public int lineCount = 100;
public float radius = 3.0f;
static Material lineMaterial;
static void CreateLineMaterial ()
{
if (!lineMaterial)
{
// Unity has a built-in shader that is useful for drawing
// simple colored things.
var shader = Shader.Find ("Hidden/Internal-Colored");
lineMaterial = Material (shader);
lineMaterial.hideFlags = HideFlags.HideAndDontSave;
// Turn on alpha blending
lineMaterial.SetInt ("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
lineMaterial.SetInt ("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
// Turn backface culling off
lineMaterial.SetInt ("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
// Turn off depth writes
lineMaterial.SetInt ("_ZWrite", 0);
}
}
// Will be called after all regular rendering is done
public void OnRenderObject ()
{
CreateLineMaterial ();
// Apply the line material
lineMaterial.SetPass (0);
GL.PushMatrix ();
// Set transformation matrix for drawing to
// match our transform
GL.MultMatrix (transform.localToWorldMatrix);
// Draw lines
GL.Begin (GL.LINES);
for (int i = 0; i < lineCount; ++i)
{
float a = i / (float)lineCount;
float angle = a * Mathf.PI * 2;
// Vertex colors change from red to green
GL.Color ( Color (a, 1-a, 0, 0.8F));
// One vertex at transform position
GL.Vertex3 (0, 0, 0);
// Another vertex at edge of circle
GL.Vertex3 (Mathf.Cos (angle) * radius, Mathf.Sin (angle) * radius, 0);
}
GL.End ();
GL.PopMatrix ();
}
}
Note: This class is almost always used when you need to draw a couple of lines or triangles, and don't want to deal with meshes. If you want to avoid surprises the usage pattern is this:
注意:这个类使用于当你需要绘制几条线或三角形,并不想使用网格。如果你想避免意外使用模式是这样的:
JavaScript:
#pragma strict
function OnPostRender() {
// Set your materials
GL.PushMatrix();
// Draw your stuff
GL.PopMatrix();
}
C#:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
void OnPostRender() {
// Set your materials
GL.PushMatrix();
// yourMaterial.SetPass( );
// Draw your stuff
GL.PopMatrix();
}
}
Where at the “// Draw your stuff” you should do SetPass() on some material previously declared, which will be used for drawing. If you dont call SetPass, then you'll get basically a random material (whatever was used before) which is not good. So do it.
在// Draw your stuff注释位置,你可以做 SetPass(),之前声明的一些材质,将永远绘制。如果你不调用SetPass,那么你将获得基本上是一个随机材质(不管是使用之前)这是不好的,因此要做这步。
Static Variables 静态变量
Select whether to invert the backface culling (true) or not (false). 是否反转背面剔除(true或false)。 | |
Mode for Begin: draw lines. 从Begin模式开始后,然后绘制线。 | |
The current modelview matrix. 返回目前的模型视图矩阵。 | |
Mode for Begin: draw quads. 从Begin模式开始后,然后绘制四边形。 | |
Mode for Begin: draw triangle strip. 从Begin模式开始后,然后绘制三角形带。 | |
Mode for Begin: draw triangles. 从Begin模式开始后,然后绘制三角形。 | |
Should rendering be done in wireframe? 是否渲染线框? |
Static Functions 静态函数
Begin drawing 3D primitives. 开始绘制3d图元。 | |
Clear the current render buffer. 清除当前的渲染缓存。 | |
Clear the current render buffer with camera's skybox. 用当前带有相机的天空盒清除渲染缓存。 | |
Sets current vertex color. 设置当前顶点颜色。 | |
End drawing 3D primitives. 结束绘制3D图元。 | |
Compute GPU projection matrix from camera's projection matrix. 从相机的GPU投影矩阵计算GPU投影矩阵。 | |
Invalidate the internally cached renderstates. 使内部渲染绘制状态无效。用来刷新内部绘制状态的统一缓存。这主要是编写本地代码时非常有用的插件,访问三维器件。 | |
Send a user-defined event to a native code plugin. 发送一个用户定义的事件到一个本地代码插件。 | |
Load the identity matrix to the current modelview matrix. 加载该恒等矩阵到道歉的模型视图矩阵。 | |
Helper function to set up an ortho perspective transform. 辅助函数用来做一个正交投影变换。 | |
Setup a matrix for pixel-correct rendering. 设置一个矩阵用于像素矫正渲染。 | |
Load an arbitrary matrix to the current projection matrix. 加载一个任意的矩阵到当前的投影矩阵。 | |
Sets current texture coordinate (v.x,v.y,v.z) to the actual texture unit. 设置纹理(x,y,z)坐标对于当前的纹理单元(多重纹理)。 | |
Sets current texture coordinate (x,y) for the actual texture unit. 设置纹理(x,y,)坐标对于当前的纹理单元。(多重纹理) | |
Sets current texture coordinate (x,y,z) to the actual texture unit. 设置纹理(x,y,z)坐标对于当前的纹理单元(多重纹理)。 | |
Multiplies the current modelview matrix with the one specified. 用当前的模型视图矩阵乘以指定的矩阵。 | |
Restores both projection and modelview matrices off the top of the matrix stack. 把投影视图矩阵和模型视图矩阵从矩阵堆栈顶部恢复。 | |
Saves both projection and modelview matrices to the matrix stack. 把投影视图矩阵和模型视图矩阵压入堆栈保存。 | |
Sets current texture coordinate (v.x,v.y,v.z) for all texture units. 设置当前纹理(v.x,v.y,v.z)坐标用于所有的纹理单元。 | |
Sets current texture coordinate (x,y) for all texture units. 设置纹理(x,y)坐标对于所有的纹理单元。 | |
Sets current texture coordinate (x,y,z) for all texture units. 设置纹理(x,y,z)坐标对于所有的纹理单元。 | |
Submit a vertex. 绘制一个顶点。 | |
Submit a vertex. 绘制一个顶点。 | |
Set the rendering viewport. 定义渲染的视口。 |
L图像库主要用来绘制常见的2d和3d几何图形。使用GL图像库,可在屏幕中绘制2d几何图形,并且该几何图形将永远显示在屏幕当中,不会因为摄像机的移动而改变。
值得注意的是,绘制2d图像时,需要使用GL.LoadOrtho()方法来将图形映射在平面中;如果绘制的是3d图形,就无须使用此方法。
使用GL图像库时,需要将所有绘制相关的内容写在OnPostRender()方法中。有关GL图像库的脚本需要绑定在摄像机中。
GL图像库的平面坐标系:原点在左下角,x轴与y轴的最大值为1。
一、绘制线
[csharp]
- using UnityEngine;
- using System.Collections;
- public class DrawLine : MonoBehaviour {
- public Material material;
- void OnPostRender()
- {
- material.SetPass(0);//设置该材质通道,0为默认值
- GL.LoadOrtho();//设置绘制2d图像
- GL.Begin(GL.LINES);//绘制类型为线段
- Draw(0, 0, 200, 100);
- Draw(0, 50, 200, 150);
- Draw(0, 100, 200, 200);
- GL.End();
- }
- //将屏幕中某个点的像素坐标进行转换
- void Draw(float x1,float y1,float x2,float y2)
- {
- GL.Vertex(new Vector3(x1 / Screen.width, y1 / Screen.height, 0));
- GL.Vertex(new Vector3(x2 / Screen.width, y2 / Screen.height, 0));
- }
- }
using UnityEngine;
using System.Collections;
public class DrawLine : MonoBehaviour {
public Material material;
void OnPostRender()
{
material.SetPass(0);//设置该材质通道,0为默认值
GL.LoadOrtho();//设置绘制2d图像
GL.Begin(GL.LINES);//绘制类型为线段
Draw(0, 0, 200, 100);
Draw(0, 50, 200, 150);
Draw(0, 100, 200, 200);
GL.End();
}
//将屏幕中某个点的像素坐标进行转换
void Draw(float x1,float y1,float x2,float y2)
{
GL.Vertex(new Vector3(x1 / Screen.width, y1 / Screen.height, 0));
GL.Vertex(new Vector3(x2 / Screen.width, y2 / Screen.height, 0));
}
}
二、绘制曲线
[csharp]
- using UnityEngine;
- using System.Collections.Generic;
- /// <summary>
- /// 记录鼠标坐标,再两两连线
- /// </summary>
- public class DrawCurve : MonoBehaviour {
- public Material material;
- private List<Vector3> lineInfo = new List<Vector3>();
- void Update ()
- {
- lineInfo.Add(Input.mousePosition);
- }
- void OnPostRender()
- {
- material.SetPass(0);//设置该材质通道,0为默认值
- GL.LoadOrtho();//设置绘制2d图像
- GL.Begin(GL.LINES);//绘制类型为线段
- for (int i = 0; i < lineInfo.Count - 1; i++)
- {
- Vector3 start = lineInfo[i];
- Vector3 end = lineInfo[i + 1];
- Draw(start.x,start.y,end.x,end.y);
- }
- GL.End();
- }
- //将屏幕中某个点的像素坐标进行转换
- void Draw(float x1, float y1, float x2, float y2)
- {
- GL.Vertex(new Vector3(x1 / Screen.width, y1 / Screen.height, 0));
- GL.Vertex(new Vector3(x2 / Screen.width, y2 / Screen.height, 0));
- }
- }
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 记录鼠标坐标,再两两连线
/// </summary>
public class DrawCurve : MonoBehaviour {
public Material material;
private List<Vector3> lineInfo = new List<Vector3>();
void Update ()
{
lineInfo.Add(Input.mousePosition);
}
void OnPostRender()
{
material.SetPass(0);//设置该材质通道,0为默认值
GL.LoadOrtho();//设置绘制2d图像
GL.Begin(GL.LINES);//绘制类型为线段
for (int i = 0; i < lineInfo.Count - 1; i++)
{
Vector3 start = lineInfo[i];
Vector3 end = lineInfo[i + 1];
Draw(start.x,start.y,end.x,end.y);
}
GL.End();
}
//将屏幕中某个点的像素坐标进行转换
void Draw(float x1, float y1, float x2, float y2)
{
GL.Vertex(new Vector3(x1 / Screen.width, y1 / Screen.height, 0));
GL.Vertex(new Vector3(x2 / Screen.width, y2 / Screen.height, 0));
}
}
三、绘制四边形
[csharp]
- using UnityEngine;
- using System.Collections;
- public class DrawQuad : MonoBehaviour {
- public Material material;
- void OnPostRender()
- {
- //绘制正四边形,提供的坐标必须是顺时针或者逆时针
- Draw(100, 100, 100, 200, 200, 200, 200, 100);
- //绘制无规则四边形
- Draw(15, 5, 10, 115, 95, 110, 90, 10);
- }
- //绘制四边形,四个点坐标
- void Draw(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
- {
- GL.PushMatrix();
- material.SetPass(0);//设置该材质通道,0为默认值
- GL.LoadOrtho();//设置绘制2d图像
- GL.Begin(GL.QUADS);//绘制类型为四边形
- GL.Vertex3(x1 / Screen.width, y1 / Screen.height, 0);
- GL.Vertex3(x2 / Screen.width, y2 / Screen.height, 0);
- GL.Vertex3(x3 / Screen.width, y3 / Screen.height, 0);
- GL.Vertex3(x4 / Screen.width, y4 / Screen.height, 0);
- GL.End();
- GL.PopMatrix();
- }
- }
using UnityEngine;
using System.Collections;
public class DrawQuad : MonoBehaviour {
public Material material;
void OnPostRender()
{
//绘制正四边形,提供的坐标必须是顺时针或者逆时针
Draw(100, 100, 100, 200, 200, 200, 200, 100);
//绘制无规则四边形
Draw(15, 5, 10, 115, 95, 110, 90, 10);
}
//绘制四边形,四个点坐标
void Draw(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
{
GL.PushMatrix();
material.SetPass(0);//设置该材质通道,0为默认值
GL.LoadOrtho();//设置绘制2d图像
GL.Begin(GL.QUADS);//绘制类型为四边形
GL.Vertex3(x1 / Screen.width, y1 / Screen.height, 0);
GL.Vertex3(x2 / Screen.width, y2 / Screen.height, 0);
GL.Vertex3(x3 / Screen.width, y3 / Screen.height, 0);
GL.Vertex3(x4 / Screen.width, y4 / Screen.height, 0);
GL.End();
GL.PopMatrix();
}
}
四、绘制三角形
[csharp]
- using UnityEngine;
- using System.Collections;
- public class DrawTriangle : MonoBehaviour {
- public Material material;
- void OnPostRender()
- {
- Draw(100,0,100,200,200,100);
- }
- void Draw(float x1, float y1, float x2, float y2, float x3, float y3)
- {
- material.SetPass(0);//设置该材质通道,0为默认值
- GL.LoadOrtho();//设置绘制2d图像
- GL.Begin(GL.TRIANGLES);//绘制类型为三角形
- GL.Vertex3(x1 / Screen.width, y1 / Screen.height, 0);
- GL.Vertex3(x2 / Screen.width, y2 / Screen.height, 0);
- GL.Vertex3(x3 / Screen.width, y3 / Screen.height, 0);
- GL.End();
- }
- }
using UnityEngine;
using System.Collections;
public class DrawTriangle : MonoBehaviour {
public Material material;
void OnPostRender()
{
Draw(100,0,100,200,200,100);
}
void Draw(float x1, float y1, float x2, float y2, float x3, float y3)
{
material.SetPass(0);//设置该材质通道,0为默认值
GL.LoadOrtho();//设置绘制2d图像
GL.Begin(GL.TRIANGLES);//绘制类型为三角形
GL.Vertex3(x1 / Screen.width, y1 / Screen.height, 0);
GL.Vertex3(x2 / Screen.width, y2 / Screen.height, 0);
GL.Vertex3(x3 / Screen.width, y3 / Screen.height, 0);
GL.End();
}
}
五、绘制3d几何图形
操作十分简单,就是将GL.LoadOrtho();注释掉即可
原来图形不会随摄像机的移动、旋转而变化,现在则会。
GL即Graphics Library。Low-Level Graphics Library。计算matrices,发出类似OpenGL的immediate模式的渲染指令,和其它低级图像任务。Graphic.DrawMesh()比GL更高效。
GL立即绘制函数,只用当前material的设置,除非你显示指定mat。否则mat可以是任何材质。并且GL可能会改变材质。
GL立即执行的,如果你在Update()里调用,它们将在相机渲染前执行,相机渲染将会清空屏幕,GL效果将无法看到。
通常GL用法是,在camera上贴脚本,并在OnPostRender()里执行。
注意:
1、GL的线等基本图元并没有UV,所以没有贴图纹理映射的,shader里仅仅做的是单色计算或者对之前的影像加以处理。
2、GL所使用的shader里必须有cull off指令,否则显示会变成如下。(如何???)
3、如果是线,颜色是GL.Color( new Color(1,1,1,0.5f)设置颜色。如果是GL.TRIANGLES或者GL.QUADS,则颜色是shader里的颜色。
方法说明:
1、GL.PushMatrix():保存Matrices至matrix stack上
GL.PopMatrix():从matrix stack上读取matrices。
2、GL.LoadPixeMatrix():改变MVP矩阵,使得transform里的xy直接对应像素,(0,0)表示屏幕ViewPort的左下角,z的范围是(-1,1),该函数改变camera的参数,所以需要GL.PushMatrix()保存和GL.PopMatrix()读取。
GL.Vertex3()的取值范围从左下角的(0,0,0)到右上角的(Screen.width,Screen.height, 0)。
使用GL.LoadPixeMatrix时,Vertex3的xy值不需要除上Screen.width和Screen.height
3、GL.LoadOrtho():设置ortho perspective,即水平视角。GL.Vertex3()取值范围从左下角的(0,0,0)到右上角的(1,1,0)即需要除上Screen.width和Screen.height。
4、OnPostRender():只有物体上有激活的相机时,才会调用该函数。当摄像机完成渲染场景后,绘制了所有物体再调用该方法。OnPostRender可以使用coroutine,加yield使用
WaitForEndOfFrame():等待至所有绘制之后,在展示frame到屏幕之前,可以做截图。可以在任务物体上使用该函数。
例子1:屏幕划线
[csharp]
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- public class Line : MonoBehaviour
- {
- public float z;
- private Material mat;
- private Vector3 vBeg;
- private Vector3 vEnd;
- private static IList<Vector3> _posList = new List<Vector3>();
- private static bool _isReady = false;
- public static bool isReady
- {
- set{ _isReady = value; }
- }
- void Start()
- {
- mat = new Material("Shader \"Lines/Colored Blended\" {" +
- "SubShader { Pass { " +
- " Blend SrcAlpha OneMinusSrcAlpha " +
- " ZWrite Off Cull Off Fog { Mode Off } " +
- " BindChannels {" +
- " Bind \"vertex\", vertex Bind \"color\", color }" +
- "} } }");//生成画线的材质
- mat.hideFlags = HideFlags.HideAndDontSave;
- mat.color = Color.green;
- mat.shader.hideFlags = HideFlags.HideAndDontSave;
- }
- public static void setPosList( ref IList<Vector3> posList )
- {
- if( _isReady )
- {
- return;
- }
- _posList = posList;
- if( _posList.Count > 1 )
- {
- _isReady = true;
- }
- }
- void OnPostRender()
- {
- if( _isReady )
- {
- vBeg = camera.WorldToScreenPoint( panelFullMap.instance.mainPlayer.position );
- vEnd = camera.WorldToScreenPoint( _posList[0] );
- GL.PushMatrix(); //保存当前Matirx
- mat.SetPass(0); //刷新当前材质
- GL.LoadOrtho();//设置pixelMatrix
- GL.Color(Color.yellow);
- GL.Begin(GL.LINES);
- GL.Vertex3( vBeg.x/Screen.width, vBeg.y/Screen.height, z );
- GL.Vertex3( vEnd.x/Screen.width, vEnd.y/Screen.height, z );
- GL.End();
- GL.PopMatrix();//读取之前的Matrix
- for( int i = 0; i < _posList.Count - 1; ++i )
- {
- vBeg = camera.WorldToScreenPoint( _posList[i] );
- vEnd = camera.WorldToScreenPoint( _posList[i+1] );
- GL.PushMatrix();
- mat.SetPass(0);
- GL.LoadOrtho();
- // GL.LoadPixelMatrix();
- GL.Begin(GL.LINES);
- GL.Color(Color.green);
- GL.Vertex3( vBeg.x/Screen.width, vBeg.y/Screen.height, z );
- GL.Vertex3( vEnd.x/Screen.width, vEnd.y/Screen.height, z );
- // GL.Vertex3( vBeg.x, vBeg.y, 0 );
- // GL.Vertex3( vEnd.x, vEnd.y, 0 );
- GL.End();
- GL.PopMatrix();
- }
- }
- }
- }
例子2:截图
[csharp]
- using System.IO;
- using UnityEngine;
- using System.Collections;
- public class ScreenShot : MonoBehaviour
- {
- void Start()
- {
- StartCoroutine(UploadPNG() );
- }
- IEnumerator UploadPNG()
- {
- yield return new WaitForEndOfFrame();
- print ("yuuuuu");
- int width = Screen.width;
- int height = Screen.height;
- Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);
- tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
- tex.Apply();
- byte[] bytes = tex.EncodeToPNG();
- File.WriteAllBytes(Application.dataPath+"/ss.png",bytes);
- UnityEditor.AssetDatabase.Refresh();
- }
- }
例子3:展示Alpha
[csharp]
- using UnityEngine;
- using System.Collections;
- public class GLTest : MonoBehaviour
- {
- public Shader shader;
- public Texture2D t2d;
- private Material mat;
- void Start()
- {
- mat = new Material(shader);
- mat.mainTexture = t2d;
- }
- void OnPostRender()
- {
- if (!mat)
- {
- Debug.LogError("Please Assign a material on the inspector");
- return;
- }
- GL.PushMatrix();
- mat.SetPass(0);
- GL.LoadOrtho();
- GL.Begin(GL.QUADS);
- GL.Vertex3(0, 0, 0.1F);
- GL.Vertex3(1f, 0, 0.1F);
- GL.Vertex3(1f, 1, 0.1F);
- GL.Vertex3(0, 1, 0.1F);
- GL.End();
- GL.PopMatrix();
- }
- }
- Shader "Custom/GLDrawLine"
- {
- Properties {
- _MainTex ("Base (RGB)", 2D) = "white" {}
- }
- SubShader
- {
- Pass
- {
- Cull off
- Blend DstAlpha zero
- Color(1,1,1,1)
- }
- }
- }