關於unity3D的GL圖像庫的使用

 GL圖象庫
GL圖象庫是底層的圖象庫,主要功能是使用程序來繪製常見的2D與3D幾何圖形。這些圖形具備必定的特殊性,他們不屬於3D網格圖形,
只會以面的形式渲染。使用GL圖象庫,可在屏幕中繪製2D幾何圖形,而且該幾何圖形將永遠顯示在屏幕當中,不會由於攝象機的移動而
改變。2D圖形的呈現方式和前面章節介紹的GUI有點相似,值得注意的是,繪製2D圖像時,須要使用GL.LoadOrtho()方法將圖形映射在
平面中;若是繪製的是3D圖形,就無須使用此方法。
使用GL圖象庫時,須要將全部繪製相關的內容寫在OnPostRender()方法中。此方法由系統自身調用,沒法手動調用。此外,有關GL圖象
庫的腳本須要綁定在Hierarchy視圖中的攝象機對象當中,不然將沒法顯示繪製的圖形
繪製線
在瞭解如何繪製線以前,先熟悉Unity中GL圖象庫的平面座標系。按照箭頭所指的方向,平面座標系的原點(0,0)位於左下腳。
值得注意的是,GL圖象庫的平面座標和普通座標是有區別的,GL圖象庫的x軸的最大值是1,y軸的最大值也爲1,而不是按照像素
來計算的,所以,在GL圖象庫的平面座標系中,每一個點的橫座標和縱座標都應當是0與1之間的浮點數,而真實的像素座標須要根據這
個浮點數來計算。
好比當前遊戲屏幕的像素寬高是500*500,在GL圖象庫平面上選擇一個點(0.5f,0.5f),那麼這個點的真實像素的橫座標和縱座標應
當是:500(屏幕寬)*0.5(x座標) = 250
500(屏幕高)*0.5(x座標) = 250
public class Script:MonoBehaviour
{
//繪製線段材質
public Material material;
//此繪製方法由系統調用
void OnPostRender()
{
if(!material)
{
Debug.LogError(「請給材質資源賦值」);
Return;
}
//設置該材質通道,0爲默認值
Material.SetPass(0);
GL.LoadOrtho();
//表示開始繪製,繪製類型爲線段
GL.Begin(GL.LINES);
//繪製線段
DrawLine(0,0,200,100);
DrawLine(0,50,200,100);
DrawLine(0,100,200,200);
GL.End();
}
void DrawLine(float x1,float y1;float x2,float y2)
{
//繪製線段,須要將屏幕中某個點的像素座標點除以屏幕完成寬或高
GL.Vetex(new Vector3(x1/Screen.width,y1/Screen.height,0));
GL.Vetex(new Vector3(x2/Screen.width,y2/Screen.height,0));
}數組

7.5.2實例----繪製曲線(228)
本例經過GL圖象庫記錄鼠標移動的軌跡而且將其以曲線的形式顯示在屏幕當中,如圖所示,具體實現原理是:記錄鼠標在Game視圖中移動
時每一點的座標,而後將鼠標移動的座標存儲在鏈表中,使用繪製方法OnPostRender()遍歷鏈表中記錄的鼠標座標點,最後經過GL圖象庫
繪製線段的方法將這些點兩兩連成一條線段
當前鼠標x軸位置:835
當前鼠標y軸位置:894
public class Script:MonoBehaviour
{
//繪製線段材質
public Material material;
Private List<Vector> lineInfo;
void Start()
{
//初始化鼠標線段鏈表
lineInfo = new List<Vector3>();
}
void Update()
{
//將每次鼠標改變的位置存儲進鏈表
lineInfo.Add(Input.mousePosition);
}
void OnGUI()
{
GUILayout.Label(「當前鼠標x軸位置:」 +Input.mousePosition.x)
GUILayout.Label(「當前鼠標y軸位置:」+Input.mousePosition.y)
}
//此繪製方法又系統調用
void OnPostRender(){
if(!material)
{
Debug.LogError(「請給材質資源賦值」);
Return;
}
//設置該材質通道,0爲默認值
material.SetPass(0);
//設置繪製2D圖象
GL.LoadOrtho();
//表示開始繪製,繪製類型爲線段
GL.Begin(GL.LINES);
//獲得鼠標信息的總數量
int size=lineInfo.Count;
//遍歷鼠標點的鏈表網絡

for(int i=0;i<size-1;i++)
{
Vector3 start = lineInfo[i];
Vector3 end = lineInfo[i+1];
//繪製線段
DrawLine(start.x,start.y,end.x,end.y);
//結束繪製
GL.End();
}
void DrawLine(float x1,float y1;float x2,float y2)
{
//繪製線段,須要將屏幕中某個點的像素座標點除以屏幕完成寬或高
GL.Vetex(new Vector(x1/Screen.width,y1/Screen.height,0));
GL.Vetex(new Vector(x2/Screen.width,y2/Screen.height,0));
}
}
在上述代碼中,咱們經過Update()方法獲取當前鼠標的位置,將每幀的鼠標位置存儲在lineInfo鏈表中,而後在OnPostRender()中遍歷
這個鏈表,將鏈表中記錄的鼠標座標點鏈接起來繪製在屏幕當中。
繪製四邊形
在平面內,由不在同一條直線的四條線段首尾順序相接組成的圖形就是四邊形。要肯定平面中的一個四邊形,就須要知道4個點,而後將
這4個點鏈接起來便可。在GL中繪製四邊形,須要使用GL.Begin(GL.QUADS)方法,該方法中參數表示須要繪製的圖形爲四邊形。若是設置
的4個點在一條直線上,或者只設置了其中3個點,或者兩個點重疊,沒法讓這4個點構成一個四邊形,程序就沒法繪製該圖形,這裏須要
讀者注意.
本例共繪製了三組幾何圖形------兩個正四邊形和一個無規則四邊形
public class Script:MonoBehaviour
{
public Material mat0;
public Material mat1;
public Material mat3;
void OnPostRender()
{
//繪製正四邊形
DrawRect(100,100,100,100,mat0);
DrawRect(250,100,100,100,mat1);
//繪製無規則四邊形
DrawQiads(15,5,10,115,95,110,90,10,mat3);
}
/**
繪製正四邊形
float x:x軸起始座標
float y:y軸起始座標
float width:正四邊形的寬
float height:正四邊形的高
*/
void DrawRect(float x,float y,float width,float height,Material mat)
{
GL.PushMatrix();
mat.SetPass(0);
GL.LoadOrtho();
//繪製類型爲四邊形
GL.Begin(GL.QUADS);
GL.Vertex3(x/Screen.width,y/Screen.height,0);
GL.Vertex3(x/Screen.width,(y+height)/Screen.height,0);
GL.Vertex3(x+width)/Screen.width,(y+height)/Screen.height,0);

GL.End();
GL.PopMatrix();
}動畫

/**
繪製無規則的四邊形
float x1:起始點1的橫座標
float y1:起始點1的橫座標
float x2:起始點2的橫座標
float y2:起始點2的橫座標
float x3:起始點3的橫座標
float y3:起始點3的橫座標
float x4:起始點4的橫座標
float y4:起始點4的橫座標
void DrawQuads(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4,Material mat)
{ GL.PushMatrix();
mat.SetPass(0);
GL.LoadOrtho();
//繪製類型爲四邊形
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();
}}
爲了說明正四邊形和無規則四邊形之間的區別,本例將它們封裝成兩個不一樣的方法,其中DrawRect()方法用於繪製無規則四邊形。
在上述代碼的最後,咱們使用GL.End()方法繪製的四邊形顯示在屏幕中。orm

7.5.4繪製三角形
繪製三角形以前,須要肯定平面中的3個點,而且保證這3個點能構成一個三角形,而後將3個點首尾鏈接起來便可。繪製三角形時,
可使用GL.Begin(GL.TRIANGLE)方法,該方法的參數爲三角形的類型.本例在屏幕中央繪製了一個正三角形,具體代碼如代碼清單
public class Script:MonoBehaviour
{
//材質
public Material mat;
void OnPostRender()
{
//繪製三角形
DrawTriangle(100,0,100,200,200,100,mat);
}
void DrawTriangle(float x1,float y1,float x2,float y2,float x3,float y3,Material mat)
{
mat.SetPass(0);
GL.LoadOrtho();
//繪製三角形
GL.Begin(GL.TRAINGLES);
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();
}}
在上述代碼中,咱們使用GL.Vertex3()方法肯定三角形三個頂點的位置,並將繪製三角形的全部方法封裝在
DrawTriangle()方法中,最後使用GL.End()方法將三角形顯示在屏幕中。須要說明的是,在調用DrawTriangle()方法時,
須要將三個點的座標與材質傳入該方法。
繪製3D幾何圖形
GL圖形庫不只支持繪製2D幾何圖形,還支持繪製3D幾何圖形,而本例將在3D世界中繪製三個平面四邊形,如圖7-17所示,
爲了讓讀者更方便看出立體效果,咱們在Game視圖中添加了一個立方體組件做爲視圖的參照物。經過隨時移動鼠標來修改攝像機朝向
的位置,能夠觀察它們之間的區別。圓圈內就是使用GL繪製的圖形,它會隨着攝像機的位置改變而發生移動,
具體的代碼如代碼清單7-19所示對象


圖7-17 立方圖形
代碼7-19
public class Script:MonoBehaviour
{
public Material mat0;
public Material mat1;
public Material mat3;
void OnPostRender()
{
//繪製正四邊形
DrawRect(100,100,100,100,mat0);
DrawRect(250,100,100,100,mat1);
//繪製無規則四邊形
DrawQuads(15,5,10,115,95,110,90,10,mat3);
}
/**
繪製正四邊形
float x:x軸起始座標
float y:y軸起始座標
float width:正四邊形的寬
float height:正四邊形的高
*/
void DrawRect(float x,float y,float width,float height,Material mat)
{
GL.PushMatrix();
mat.SetPass(0);
//繪製類型爲四邊形
GL.Begin(GL.QUADS);
GL.Vertex3(x/Screen.width,y/Screen.height,0);
GL.Vertex3(x/Screen.width,(y+height)/Screen.height,0);
GL.Vertex3(x+width)/Screen.width,(y+height)/Screen.height,0);
GL.Vertex3(x+width)/Screen.width, y/Screen.height,0);

GL.End();
GL.PopMatrix();
}索引

/**
繪製無規則的四邊形
float x1:起始點1的橫座標
float y1:起始點1的橫座標
float x2:起始點2的橫座標
float y2:起始點2的橫座標
float x3:起始點3的橫座標
float y3:起始點3的橫座標
float x4:起始點4的橫座標
float y4:起始點4的橫座標
void DrawQuads(float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4,Material mat)
{ GL.PushMatrix();
mat.SetPass(0);
//繪製類型爲四邊形
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();
}}
在繪製四邊形時,首先須要使用GL.Begin(GL.QUADS)方法設定渲染模型的類型爲四邊形,而後使用GL.Vertex3()設置
四邊形每一個點的座標,最後使用GL.Eng() 方法將四邊形渲染在屏幕當中移動攝像機的代碼.
MoveCamera.cs
public class MoveCamera:MonoBehaviour
{
//攝像機參照的模型
public Transform target;
//攝像機距離模型的默認距離
private float distance = 2.0f;
//鼠標在x軸和y軸方向移動的角度
float x;
float y;
//限制旋轉角度的最小值與最大值
float yMinLimit=-20.0f
float yMaxLimit=80.f
//x和y軸方向的移動速度
float xSpeed = 250.0f;
float ySpeed = 120.0f;
void Start(){
//初始化和y軸角度等於參照模型的角度
Vector2 angles =transform.eulerAngles;
x=angles.y;
y=angles.x;
if(rigidbody)
{
rigidbody.freezeRotation = true;
}
void LateUpdate()
{
if(target)
{
//根據鼠標的移動修改攝像機的角度
x+=Input.GetAxis("Mouse X")*xSpeed*0.02f;
y-=Input.GetAxis("Mouse Y")*ySpeed*0.02f;
y = ClampAngle(y,yMinLimit,yMaxLimit);
Quaternion rotation =Quaternion.Euler(y,x,0);
Vector3 position = rotation*new Vector3(0.0f,0.0f,(-distance))+target.position;
//設置模型的位置與旋轉
transform.rotation =rotation;
transform.position =position;
}
}
float ClampAngle(float angle,float min,float max);
}
}
在LateUpdate()方法中經過鼠標的移動來觀察模型,該模型的對象包尋在target變量當中。遊戲

線渲染器
線渲染器主要用於在3D世界中渲染線段,與GL圖象庫渲染相比,它更加專業,能夠控制線段的組細程度
以及線段的數量,而且以網格對象的形式出如今3D世界中。使用線渲染器繪製線段時,必須先肯定這條線段兩個
端點的位置。須要說明的是,這兩個點不是平面中的點而是3D世界中的點
線渲染器以組件的形式出現Unity當中,因此須要將它綁定在某個遊戲對象中。這裏咱們在Unity導航中選擇
"GameObject"--->"CreateEmpty"菜單項建立一個空的遊戲對象,而後雜Hierarchy視圖中選擇該對象後,繼續在
Unity導航菜單中選擇"Component"-->"Line Render"菜單項,便可將線渲染器組件添加至遊戲對象中,接着是設置
參數。
本例中繪製了3條相連的線段,它是以4個頂點肯定的3條線段,而且它們首尾相接成一條線。這個線段以立體的形式
出如今3D世界中
public class Script:MonoBehaviour
{
//線段對象
private CameObject LineRenderGameObject;
//線段渲染器
private LineRenderer lineRenderer;
//設置線段的頂點數,4個點肯定3條直線
private int lineLength = 4;
//記錄4個點,鏈接一條線段
private Vector3 v0 = new Vector3(1.0f,0.0f,0.0f);
private Vector3 v1 = new Vector3(2.0f,0.0f,0.0f);
private Vector3 v2 = new Vector3(3.0f,0.0f,0.0f);
private Vector3 v3 = new Vector3(4.0f,0.0f,0.0f);

void Start()
{
//得到遊戲對象
LineRenderGameObject = GameObject.Find("ObjLine");
//得到線渲染器組件
lineRenderer = (LineRendererGameObject.GetComponent("LineRenderer");
//設置線的頂點數
lineRenderer.SetVertexCount(lineLength);
//設置線的寬度
lineRenderer.SetWidth(0.1f,0.1f);
}
void Update(){
//使用4個頂點渲染3條線段
lineRender.SetPosition(0,v0);
lineRender.SetPosition(1,v1);
lineRender.SetPosition(2,v2);
lineRender.SetPosition(3,v3);
}
}
在上述代碼,咱們首先獲取了線渲染器組件對象,而後設置頂點的數量,最後調用SetPosition()方法將線段顯示在屏幕中。
SetPosition()方法的第一個參數表示每一個點的ID,讓它保持惟一性,第一個參數表示該頂點的3D的位置.事件

網格渲染
「Component」?Mesh?」Mesh Filter」菜單項與」Mesh Renderer」菜單項,便可將組件添加至遊戲對象自己。
本例在屏幕中渲染了兩個網格面對象。由於網格面又三角形網格頂點的位置,三角形由3個頂點組成,因此它們的規律是:
一個三角形數組長度就是3,兩個三角形數組長度就是6,依次類推該數組的長度只多是3的倍數。最後繪製網格時使用triangles數組,
數組中的ID和Vertices(網格頂點)的頂點ID一一對應。
分5等份填充
徹底填充
public class script:MonoBehaviour
{
//構成三角形1的位置
Vector3 v0 = new Vector3(5,0,0);
Vector3 v1 = new Vector3(0,5,0);
Vector3 v2 = new Vector3(0,0,5);
//構成三角形2的位置
Vector3 v3 = new Vector3(-5,0,0);
Vector3 v4 = new Vector3(0,-5,0);
Vector3 v5 = new Vector3(0,0,-5);
//構成三角形1的貼圖比例
Vector2 u0 = new Vector2(0,0);
Vector2 u1 = new Vector2(0,5);
Vector2 u2 = new Vector2(5,5);
//構成三角形2的貼圖比例
Vector2 u3 = new Vector2(0,0);
Vector2 u4 = new Vector2(0,1);
Vector2 u5 = new Vector2(1,1);
void Start()
{
//獲得網格渲染器對象
MeshFilter meshFilter =(MeshFilter)GameObject.Find("face").GetComponent(typeof(MeshFilter));
//經過渲染器對象獲得網格對象
Mesh mesh = meshFilter.mesh;
//設置三角形頂點的數組,6個點表示設置了兩個三角形
mesh.Vertices = new Vector3[]{v0,v1,v2,v3,v4,v5};
//設置三角形面上的貼圖比例
mesh.uv = new Vector2[] {u0,u1,u2,u3,u4,u5};
//設置三角形索引,繪製三角形
mesh.triangles = new int[]{0,1,2,3,4,5};
}}
代碼最後的mesh.triangles表示設定三角形的索引數組,該數組中的ID表示相對頂點數組中的座標。目前這個數組中的元素是0、一、二、三、4和5,
對應頂點數組中6個頂點座標。由於3個點肯定一個三角形面,因此這裏使用定點數組中0,1,2肯定了一個三角形,3,4,5又肯定了一個
三角形。

遊戲實例—控制人物移動
爲了讓讀者更清晰地瞭解如何控制主角移動與播放骨骼動畫,下面咱們將角色控制器組件的人物動畫拆開,使用代碼自行實現他的行走動畫。運行遊戲後,按鍵盤鍵上的
「W」,」S」,」A」,」D」來移動主角。
public class Script:MonoBehaviour
{
//人物行走的方向狀態
public const int HERO_UP=0;
public const int HERO_RIGHT=1;
public const int HERO_DOWN=2;
public const int HERO_LEFT=3;
//人物當前的行走方向
public int state = 0;
//人物移動速度
public int moveSpeed =10;
//初始化人物的默認位置
public void Awake(){
state =HERO_DOWN;
}
void Update(){
//獲取控制的方向數據
float KeyVertical =Input.GetAxis("Vertical");
float KeyHorizontal = Input.GetAxis("Horzontal");
if(KeyVertical ==-1)
{
setHeroState(HERO_LEFT);
}else if(KeyVertical ==1)
{
//設置人物動畫往右行走
setHeroState(HERO_RIGHT);
}
if(KeyHorizontal ==1)
{
setHeroState(HERO_DOWN);
}else if(KeyHorzontal ==-1)
{
setHeroState(HERO_UP);
}
if(KeyVertical ==0 &&KeyHorizontal ==0)
{
animation.Play();
}
}
public void setHeroState(int newState)
{
//根據當前人物方向與上一次備份方向計算出模型旋轉的角度
int rotateValue =(newState-state)*90;
Vector3 transformValue =new Vector3();
//播放行走動畫
animation.Play("walk");
//模型移動的位移的數值
switch(newState){
case HERO_UP:
transformValue = Vector3.forward*Time.deltaTime;
break;
case HERO_DOWN:
transformValue =(-Vector3.forward).Time.deltaTime;
break;
case HERO_LEFT:
transformValue = Vector3.left*Time.deltaTime;
break;
case HERO_RIGHT:
transformValue = (-Vector3.left)*Time.deltaTime;
break;
}
//模型旋轉
transform.Rotate(Vector3.up,rotateValue);
//移動人物
transform.Translate(transformValue *moveSpeed,Space.World);
state = newState;
}
}
本例使用遊戲狀態機將主角的行走分爲4個狀態:向前行走,向後行走,向左行走,向右行走。按下不一樣的方向鍵後,
使用animation.Play()方法播放行走動畫,該方法的參數爲動畫名稱,最後根據當前的行走狀態計算模型的旋轉角度,
使其按照正確的方向行走。
本章首先介紹瞭如何處理鍵盤與鼠標輸入事件,好比按下事件,擡起事件和長按事件等,接着介紹了自定義按鍵事件、
模型與動畫,而後介紹瞭如何使用GL圖像庫繪製2D與3D的線段與網絡模型,以及線渲染器與網格渲染器的繪製方法,
最後以一個實例的形式向讀者介紹如何使用鍵盤控制主角移動而且播放骨骼動畫。ip

相關文章
相關標籤/搜索