图像中的unity 图像处理square是什么意思

这篇作为上一篇的补充介绍,主要讲Unity里面的投影矩阵的问题:
上篇的链接
关于Unity中的Camera,圣典里面对每一项属性都做了简要的介绍,没看过的小伙伴传送门在下面
一、裁剪面
先从这个专业的词汇开始,以下是圣典对裁剪面的介绍:
The Near and Far Clip Plane properties determine where the Camera's view begins and ends. The planes are laid out perpendicular to the Camera's direction and are measured from the its position. The Near plane is the closest location that will be rendered, and the Far plane is the furthest.
近裁剪面及远裁剪面属性确定相机视野的开始和结束。平面是布置在与相机的方向垂直的位置,并从它的位置测量。近裁剪面是最近的渲染位置,远平面是最远的渲染位置。
这句话感觉说了和没说差不多,因为我们没有看到过裁剪面,所以了解裁剪面的第一步,我们需要在Unity当中去直观的看看它
下图,当我们近距离观察Camera的时候,会发现一个用白线画的金字塔(四棱锥),这很好理解,他表示了Camera的视野范围,奇怪的是这个金字塔(四棱锥)少了一个角,从而金字塔不仅有了底面,还有一个顶面。
相信猜也能猜到了,金字塔的顶部这个面,是近裁剪面(near clip planes),底面,则是远裁剪面(near clip planes)
那么说了半天,裁剪面有什么用呢?
我们继续在Unity的摄像机中改变Clipping Planes的值,看看变化,首先把Clipping Planes的near和far分别调为2和6
如下图预览界面,在近裁剪面和远裁剪面之间没有包含物体,渲染的图像里是不会有物体的
增加far的值,现在立方体的很小一块包含进去了,但是我们看预览界面,并看不出它是立方体,只能看出平面效果
好的,继续增加,现在整个立方体都包含进来了,看预览,终于可以明显看出是正方体了
这个例子说明了Camera似乎只渲染近裁剪面与远裁剪面之间的物体,这个原理就好比平面图的渲染,我们需要对图片进行裁剪完成后,程序才知道要渲染的范围,无论这张图是全部需要还是只需要一部分,第一步,都是裁剪。现在,3D的渲染也需要裁剪,于是近裁剪面与远裁剪面就诞生了,只不过裁剪的范围并不是平面的,而是立体的(被切掉顶端的金字塔),这个立体的形状,我们称之为视裁剪体。
二、视裁剪体
视裁剪体,专业的叫法是视锥体(fusum),它由6个面构成,上下,左右,前后,先看圣典里面的介绍:
The outer edges of the image are defined by the diverging lines that correspond to the corners of the image. If those lines were traced backwards towards the camera, they would all eventually converge at a single point. In Unity, this point is located exactly at the camera's transform position and is known as the centre of perspective. The angle subtended by the lines converging from the top and bottom centres of the screen at the centre of perspective is called the field of view (often abbreviated to FOV).
在影像的边缘被称为对应影像角落的偏离线。如果被描绘的那些线向相机的后方转,他们最终将汇聚在一个点上。在Unity, 这个点恰好位于被称为视图中心的变换位置上。在视图中,屏幕中顶部的中心和底部的中心汇聚的线的夹角,被称为视野(通常缩写成FOV)。
As stated above, anything that falls outside the diverging lines at the edges of the image will not be visible to the camera, but there are also two other restrictions on what it will render. The near and far clipping planes are parallel to the camera's XY plane and each set at a certain distance along its centre line. Anything closer to the camera than the near clipping plane and anything farther away than the far clipping plane will not be rendered.
如上所述, 任何超出影像边缘的偏离先之外的东西都是看不见的。渲染还有另外两个限制条件。近裁剪面和远裁剪面是与相机的XY平面平行的,并且每个裁剪面离中心线有一定的距离。任何在近裁剪面的之内和超出远裁剪面之外的物体都不会被渲染。
我们在上面已经了解了远近裁剪面,即前后,那么上下左右四个面又是怎么定义的呢?上面的介绍已经涉及到了,就是FOV的概念。
继续回到Unity当中,看下FOV的具体效果,修改Field of View的值,30,视锥体收缩,正方体不再内部
FOV修改为60,明显感觉视锥体扩张,预览又能看到正方体了
从上面看FOV的值似乎决定了上下左右四个面的夹角,而且其大小是用度来表示的,这里的60即表示60度
好了,现在一个视锥体的所有参数都已经明确了,已知Camera的坐标,只要知道远近裁剪面的值,FOV的值即可定义一个唯一的视锥体
说了半天,视锥体要怎么使用?ok,接下来开始正题,投影变换。
三、投影变换
Unity中Camera的投影变换分为两种:透视投影和正交投影。
简要说明两者的区别,正交投影的观察体是长方体,是规则的,它使用一组平行投影将三维对象投影到投影平面上去,相信对Unity了解比较深入的同学都知道正交投影的功能,距离Camera的远近并不会影响物体的缩放,比如说距离10m和1000m的实际大小相同的物体,呈现在画面里的大小也是相同的,这显然是我们不希望的,3D游戏模拟的是现实生活,而在现实生活当中,离我们远的物体,看起来当然比较小,而即使是一部手机,放在眼睛前方的时候,看起来,却会硕大无比。于是正交投影在3D游戏当中的使用就非常有限了。
接下来是透视投影,这是3D游戏中广为使用的一种技术,它使用一组由投影中心产生的放射投影线,将三维对象投影到投影平面上去。透视投影的观察体就是以上一直在说的视锥体。它具有通过物体远近来缩放的能力,现在,需要把视锥体包含的物体投影成画面,这个过程,需要做的变换,就是投影变换
那么为什么要变换呢?
视锥体实际上不是一个规则体,这对于我们做裁剪很不利,从3D物体到画面的过程,通常需要经历以下三步:
1. 用透视变换矩阵把顶点从视锥体中变换到裁剪空间的规则观察体(CVV)中2. 使用CVV进行裁剪3. 屏幕映射:将经过前述过程得到的坐标映射到屏幕坐标系上。
这个过程,可以用一张图来表示(图摘自它处)
从视锥体变换到立方体的过程中,近裁剪面被放大变成了立方体的前表面,远裁剪面被缩小变成了立方体的后表面,这就解释了为什么透视投影可以将物体的远近很直观表达出来的原因,很简单,因为它放大了近处的物体,缩小了远处的物体。
那么怎么做这个变换呢,我们可以理解为视锥体中某一个点(x,y,z,1)与某一个矩阵相乘得到的新点(x1,y1,z1,1)即为对应CVV中的点,这样把视锥体中所有的点与该矩阵相乘,获得的就是一个CVV。而这个矩阵,就是透视投影矩阵。
直接亮出这个矩阵的值,想看详细推导的同学,给个链接:
这里有很多参数的意义用下图来表示
对于一个视锥体,我们取它的截面一般有如下两种方法,不过一般都取yz面作为截面来计算参数,这里我们要取FOV,near,far,botton,top,right,left的值,其中botton,top,right,left是投影平面的上下左右边界值,投影平面,就是近裁剪面。
四、修改投影矩阵建立一个非标准投影
我们继续回归到Unity当中,Unity关于Camera投影矩阵的文档相当相当的少,唯一可用的就是Camera.projectionMatrix的API里面零星的介绍,链接:
但至少我们是可以输出投影矩阵看一下的
print(Camera.main.projectionMatrix); //这句话输出主摄像机的投影矩阵
上图看到了投影矩阵的值,FOV=60,near=0.3,far=1000的情况下,进行计算,发现除了第一个值有问题其他都正确。
第一个值为什么是1.08878?
经过研究,我发现Unity有一个特性,无论怎么修改窗口的比例,m【1,1】的值总是不变,固定为1.73205但是,只要改变FOV,它就会改变,所以Unity一定是把FOV定义为投影平面的上边缘与下边缘的夹角,即top=near*tan(FOV/2),而right就不能通过right=near*tan(FOV/2)来计算了,而是要用right=top*aspect这条公式,我们调节屏幕尺寸的时候,实际上改变了m【0,0】的结果而不会改变其他值。
我们写一个脚本去改变投影矩阵的值,看看效果
using UnityEusing System.Cpublic class example : MonoBehaviour {public Matrix4x4 originalPvoid Update() {//改变原始矩阵的某些值Matrix4x4 p = originalPCamera.main.projectionMatrix =}public void Awake() {originalProjection = Camera.main.projectionMprint(Camera.main.projectionMatrix);}}
这里取E01=0.5,发现远近裁剪面变成平行四变形,相应的画面也斜了
其他的我就不演示了,改变其他的值会得到相应的效果
原因很简单,还是要贴出之前推导出来的公式
M矩阵的m01我们把他从0改到了0.5,影响的是x坐标变换的结果,本来x坐标是与y无关的,现在随着y的增加,x也会增加
如下图,相当于本来正方形中的每一个像素与y都无关,现在每一个像素在y不为0的时候都会向右平移0.5y的距离,这样,就导致看起来像平行四边形了
其他的就不一一推导了,反正在做投影的时候会涉及到这一块,这样以后涉及到投影矩阵的时候大家就不会那么迷茫了
最后贴一串代码,是在圣典上发现的,实现画面像水一像波动的特效,也是通过修改投影矩阵的方式实现的
复制黏贴后,加在主摄像机上就可以实现了,这么强大的特效居然几行代码就可以搞定,实在觉得不可思议。
using UnityEusing System.C//让相机以流行的方式晃动public class example : MonoBehaviour {public Matrix4x4 originalPvoid Update() {//改变原始矩阵的某些值Matrix4x4 p = originalPp.m01 += Mathf.Sin(Time.time * 1.2F) * 0.1F;p.m10 += Mathf.Sin(Time.time * 1.5F) * 0.1F;Camera.main.projectionMatrix =}public void Awake() {originalProjection = Camera.main.projectionM}}
后面会继续回归VR的主题,继续去详细解释脚本里面的东西。
阅读(...) 评论()博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Unity3D中常见的三类Shader的区别与用法 | Unity3D教程手册
当前位置 :
>> Unity3D中常见的三类Shader的区别与用法
Unity3D中常见的三类Shader的区别与用法
中常见的三类Shader:Diffuse、Diffuse Bumped、Bumped Specular。
这三种类型为常用类型,其中Bumped需要增加Normal法线贴图来实现凹凸。
Decal:这种材质为贴花材质,即相当于Mask类型,可以再Decal(RGBA)贴与一个带有Alpha通道的图像,形成和原图像相叠加的效果。
Diffuse Detail:这种材质可以创造出污迹和划痕的效果,即相当于Blend混合材质。
Reflective:其中各种类型可以创造出金属反射效果,需要增加Cubmap贴图。
Transparent:其中各种类型可以创造出透明的效果,需要增加具有Alpha的通道贴图。
注意:如果要做玻璃贴图,Alpha如果全是灰色或黑色(即要求全透明),那么Alpha就会失效,如果要全透明,材质Alpha其中必须至少有1像素为白色。
Nature:其中Soft Occlusion Leaves类型主要应用于片状的树叶材质。
【上一篇】
【下一篇】
您可能还会对这些文章感兴趣!用图片在 Unity 中做全屏背景
招聘信息:
&&& 如果你需要将一个图片做为场景的背景,且需要图片完全匹配屏幕的宽和高,就试试这个吧。
&&& 导入资源包后只需要将脚本赋予相机,并设定你要作为背景的图像即可。他会自动将图像尺寸与屏幕匹配,如果你屏幕是480*320,那么你的图最好也做480*320的。比例不对可能出现拉伸。还有一个参数是设定距离,也就是这个背景与相机的间距。
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量3321点击量3298点击量2721点击量2226点击量2203点击量2144点击量2119点击量1996点击量1968
&2018 Chukong Technologies,Inc.
京公网安备89关于unity3D的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坐标) = 250public class Script:MonoBehaviour{//绘制线段材质public M //此绘制方法由系统调用 void OnPostRender() {
if(!material)
Debug.LogError(“请给材质资源赋值”);
//设置该材质通道,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轴位置:894public class Script:MonoBehaviour{//绘制线段材质public MPrivate List&Vector& lineIvoid 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(“请给材质资源赋值”);R}//设置该材质通道,0为默认值material.SetPass(0);//设置绘制2D图象GL.LoadOrtho();//表示开始绘制,绘制类型为线段GL.Begin(GL.LINES);//得到鼠标信息的总数量int size=lineInfo.C//遍历鼠标点的链表
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()方法绘制的四边形显示在屏幕中。
7.5.4绘制三角形绘制三角形之前,需要确定平面中的3个点,并且保证这3个点能构成一个三角形,然后将3个点首尾连接起来即可。绘制三角形时,可以使用GL.Begin(GL.TRIANGLE)方法,该方法的参数为三角形的类型.本例在屏幕中央绘制了一个正三角形,具体代码如代码清单public class Script:MonoBehaviour{ //材质public Mvoid 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-19public 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.cspublic class MoveCamera:MonoBehaviour{ //摄像机参照的模型 public T //摄像机距离模型的默认距离 private float distance = 2.0f; //鼠标在x轴和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.eulerA x=angles.y; y=angles.x; if(rigidbody) {
rigidbody.freezeRotation = } 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.
//设置模型的位置与旋转
transform.rotation =
transform.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 LineRenderGameO //线段渲染器 private LineRenderer lineR //设置线段的顶点数,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.//设置三角形顶点的数组,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、1、2、3、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.deltaT
case HERO_DOWN:
transformValue =(-Vector3.forward).Time.deltaT
case HERO_LEFT:
transformValue =
Vector3.left*Time.deltaT
case HERO_RIGHT:
transformValue = (-Vector3.left)*Time.deltaT
} //模型旋转 transform.Rotate(Vector3.up,rotateValue); //移动人物 transform.Translate(transformValue *moveSpeed,Space.World); state = newS }}本例使用游戏状态机将主角的行走分为4个状态:向前行走,向后行走,向左行走,向右行走。按下不同的方向键后,使用animation.Play()方法播放行走动画,该方法的参数为动画名称,最后根据当前的行走状态计算模型的旋转角度,使其按照正确的方向行走。本章首先介绍了如何处理键盘与鼠标输入事件,比如按下事件,抬起事件和长按事件等,接着介绍了自定义按键事件、模型与动画,然后介绍了如何使用GL图像库绘制2D与3D的线段与网络模型,以及线渲染器与网格渲染器的绘制方法,最后以一个实例的形式向读者介绍如何使用键盘控制主角移动并且播放骨骼动画。
随笔 - 151

我要回帖

更多关于 unity 图像处理 的文章

 

随机推荐