unity 如何实现unity3d 屏幕坐标

接着上篇文章,我们实现了SSR效果。
其中的在屏幕空间进行光线追踪的方法是通用的。借此我们再实现一种屏幕空间的效果,即屏幕空间阴影。
文中的图片来自Catlike coding
完成的工程:
首先我们要了解一下原生的阴影是怎么实现的,这里我们只讨论Directional Light。
首先,我们将Directional Light视作一个相机,对整个场景进行绘制。我们只需要其中的深度信息。(如果你尝试过自己写一个可以产生阴影的Shader,应该知道这个绘制是通过调用ShadowCaster类型的pass来实现的)
通过这样渲染的一张ShadowMap,在我们渲染主相机的画面时,对每一个像素,我们获得它的世界坐标,然后将该世界坐标转换到Directional Light的坐标系下,采样对应的ShadowMap中的点。如果我们采样出来的深度,大于该坐标的深度,我们认为该点没有被阻挡。否则认为该点处于阴影中。
这就是ShadowMap方法的简单描述。在Unity的Directional Light流程中,采用的是Cascade ShadowMap,此时会有若干个不同分辨率的ShadowMap被生成,分别对应与相机距离不同的区域,这样可以做到相机较近的区域,分辨率较高,阴影质量更好;较远的区域分辨率较低,质量一般(但是远了你也看不出来)。
Cascade ShadowMap示例
不同于其他类型的光源,在主相机渲染时,我们求一个点的光照度,并不是直接去转换坐标系然后采样ShadowMap。在Directional Light流程中,在主相机渲染之前,Unity会将Cascade ShadowMap转化为一张屏幕空间的阴影贴图(Screen Space Mask,当然该过程也需要转换坐标系去比较深度等等)。然后在主相机渲染时直接取采样这张屏幕空间阴影贴图获得光照度。
屏幕空间的阴影贴图示例
我们待会儿会通过操作这张屏幕空间阴影来实现我们的效果。
这种阴影实现毫无疑问是目前的主流方法。但是它也有不少问题,比如Shadow Acne现象。我们之前说到,判断一个点是否在阴影中,是通过深度比较进行的。但是我们要判断一个像素是否在阴影中时,因为深度贴图的精度问题,可能会出现被周围的差异极小的像素遮挡的情况。
屏幕空间阴影
屏幕空间阴影基于屏幕空间光线追踪实现阴影效果。
最大的好处就是让不参与ShadowMap绘制的物体也可以投出阴影。
而且作为一个屏幕效果,其效率与场景复杂度无关。
在绘制大量的小型物体时,这一优势是很明显的。
下图是一个效果关闭开启的对比。图中的草是Unity的Terrain系统绘制的,默认不开启阴影。可以看到开启屏幕空间阴影后画面提升明显。
阅读(...) 评论()程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
UGUI研究院之开始学习搭建界面自适应屏幕(一)
UGUI研究院之开始学习搭建界面自适应屏幕(一)
围观240758次
编辑日期: 字体:
UGUI已经beat21了。。直觉已经告诉我正式版马上就要来了。刚好今天有时间,我就抽空学习一下UGUI。以前都是搞NGUI,衷心希望UGUI的诞生可以彻底干掉NGUI(目前还不太现实)。今天主要研究的是搭建界面还有自适应屏幕相关的,这里记录下我的学习笔记欢迎大家一起讨论嘿嘿。
如下图所示,我们先看Canvas,Render Mode一共有三种模式。
1.Screen Space – overlay
此模式不需要UI摄像机,UI将永远出现在所有摄像机的最前面。我觉得overlay有问题,如果我想在UI前面放个东西就不行了,因为可能在UI前面放一个特效或者UI啥的。。
2.Screen Space- Camera 此模式是我决定采取的,它需要提供一个UICamera 。这样就和NGUI的原理很像了,如果我想在UI前面加特效我可以在创建一个摄像机深度大于这个UICamera就行了。
3.World Space 这个就是完全3D的UI,UGUI的例子大多都采用它,但是我觉得目前我还是用不到。
如下图所示,在看Canvas Scaler。UGUI在处理自适应这块不需要我们自己在写算法了。
UI Scale Mode :Scale With Screen Size 表示以宽度为标准缩放。。 因为我搭建界面的时候是960X640所以这里我写960X640。
Screen Match Mode 选择 Expand 这个就是UGUI自己自适应屏幕的选项了。
补充: Canvas Scaler 选择 Scale With Screen Size, Screen Match Mode 选择 Match Width Or Height,比例设为1,即只和高度进行适配;
如下图所示,看看我的层次视图
Main Camera 就是主摄像机,也就是透视摄像机,它的深度最小最先绘制。
Canvas就是画布了,下面挂的UICamera 和 UIForward摄像机。
UICamera 下面挂着所有的uGUI的UI控件,它的深度大于MainCamera。
UIForward 就是前面我们说的有些东西要在UICamera的前面显示。注意Camera的的size = 3.2 ,也就是960/640=3.2 。
接着在UICamera下面挂UI控件吧。。这个比较简单就不细说了。。
因为UI的自适应UGUI已经帮我们做了,那么我们要做的就是3DCamera的自适应。把下面这个脚本挂在Main Camera上即可。
123456789101112131415161718
using UnityEngine;using System.Collections;using UnityEngine.UI;public class CameraScale : MonoBehaviour {& void Start () {
int ManualWidth = 960;
int ManualHeight = 640;
int manualHeight;
if (System.Convert.ToSingle(Screen.height) / Screen.width & System.Convert.ToSingle(ManualHeight) / ManualWidth)
manualHeight = Mathf.RoundToInt(System.Convert.ToSingle(ManualWidth) / Screen.width * Screen.height);
manualHeight = ManualHeight;
Camera camera = GetComponent&Camera&();
float scale =System.Convert.ToSingle(manualHeight / 640f);
camera.fieldOfView*= scale; }}
记得增加一个UIForward 的层, 这样如果想在UI的前面添加特效 直接把它的特效的Layer设置成UIForward即可。
最后,由于我也正在学习,如果有不对的地方欢迎大家在下面给我留言。谢谢啦,呼呼~~~
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
FingerGestures研究院之初探Unity手势操作(一)
FingerGestures研究院之初探Unity手势操作(一)
围观92881次
编辑日期: 字体:
昨天搬家,我被无情的从4楼请上了10楼。原因就是房东们为了争家产打官司,受伤的永远是我们这些打工的租房的码农,呵呵!结果就是我们两家做了一个调换把房子换了一下。东西太多了,真的好累啊,好累啊~~前几天有个朋友问我Unity手势操作,后来我还帮他做了一个例子。我觉得在Unity中用这个手势操作的插件会很方便。以前我只是知道FingerGestures,但是没有深入的用过,这两天学习了一下。真的很好用。
最近研究了一下Unity中的一个手势操作的插件FingerGestures。它能很方便监听到Unity中的各种手势事件:上下左右四方向的滑动事件、按下事件、抬起事件、移动事件、连击事件、长按事件等等。它同时支持触摸屏操作与鼠标操作,总起来说使用起来还是比较方便的,今天写下教程记录这个插件的详细使用步骤。首先下载这个插件,大家可以在圣典上找这个插件的下载地址,当然也可以在本文最后下载该插件。
我看了一下这个插件底层的实现步骤,他是通过C#代理的形式来实现手势操作的。如下图红圈内所示,这五个重要的预设用来监听触摸与鼠标的手势事件。包括:单手触摸事件、双手触摸事件、鼠标事件、触摸事件。这里我们使用一个单手的事件,如图中所示将Finger Gertures Initializer拖拽入左侧层次视图中。
OK,上面我们说了该插件是通过C#代理形式来接收事件消息的,所以我们需要用脚本来注册这些事件从而开始接收消息。接着创建一个立方体对象用以处理手势操作,当然你也可以处理游戏中的任何对象。编写脚本FingerEvent.cs ,把这个脚本挂在这个立方体对象之上。
FingerEvent.cs脚本
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
using UnityEngine;using System.Collections;&public class FingerEvent :&&MonoBehaviour {&&&&&void OnEnable()&&&&{&&&& //启动时调用,这里开始注册手势操作的事件。&&&&& //按下事件: OnFingerDown就是按下事件监听的方法,这个名子可以由你来自定义。方法只能在本类中监听。下面所有的事件都一样!!!&&&&&&&&FingerGestures.OnFingerDown += OnFingerDown;&&&&&&&&//抬起事件
FingerGestures.OnFingerUp += OnFingerUp; &&&&//开始拖动事件 &&&&FingerGestures.OnFingerDragBegin += OnFingerDragBegin;&&&&&&&&//拖动中事件...&&&&&&&&FingerGestures.OnFingerDragMove += OnFingerDragMove;&&&&&&&&//拖动结束事件&&&&&&&&FingerGestures.OnFingerDragEnd += OnFingerDragEnd;
//上、下、左、右、四个方向的手势滑动
FingerGestures.OnFingerSwipe += OnFingerSwipe;
//连击事件 连续点击事件
FingerGestures.OnFingerTap += OnFingerTap;
//手指触摸屏幕中事件调用一下三个方法
FingerGestures.OnFingerStationaryBegin += OnFingerStationaryBegin;
FingerGestures.OnFingerStationary += OnFingerStationary;
FingerGestures.OnFingerStationaryEnd += OnFingerStationaryEnd;
//长按事件
FingerGestures.OnFingerLongPress += OnFingerLongPress;&&&&&}&&&&&void OnDisable()&&&&{&&&& //关闭时调用,这里销毁手势操作的事件&&&& //和上面一样&&&&&&&&FingerGestures.OnFingerDown -= OnFingerDown;
FingerGestures.OnFingerUp -= OnFingerUp;
FingerGestures.OnFingerDragBegin -= OnFingerDragBegin;&&&&&&&&FingerGestures.OnFingerDragMove -= OnFingerDragMove;&&&&&&&&FingerGestures.OnFingerDragEnd -= OnFingerDragEnd;
FingerGestures.OnFingerSwipe -= OnFingerSwipe;
FingerGestures.OnFingerTap -= OnFingerTap;
FingerGestures.OnFingerStationaryBegin -= OnFingerStationaryBegin;
FingerGestures.OnFingerStationary -= OnFingerStationary;
FingerGestures.OnFingerStationaryEnd -= OnFingerStationaryEnd;
FingerGestures.OnFingerLongPress -= OnFingerLongPress;&&&&}&&&&&//按下时调用&&&&void OnFingerDown( int fingerIndex, Vector2 fingerPos )&&&&{
//int fingerIndex 是手指的ID 第一按下的手指就是 0 第二个按下的手指就是1。。。一次类推。
//Vector2 fingerPos 手指按下屏幕中的2D坐标&
//将2D坐标转换成3D坐标&&&&&&&&transform.position = GetWorldPos( fingerPos );
Debug.Log(" OnFingerDown ="&&+fingerPos);&&&&}& //抬起时调用 void OnFingerUp( int fingerIndex, Vector2 fingerPos, float timeHeldDown ) {&
Debug.Log(" OnFingerUp ="&&+fingerPos); }& //开始滑动 void OnFingerDragBegin( int fingerIndex, Vector2 fingerPos, Vector2 startPos )&&&&{&&
Debug.Log("OnFingerDragBegin fingerIndex =" + fingerIndex&&+ " fingerPos ="+fingerPos +"startPos =" +startPos);&&&&} //滑动结束 void OnFingerDragEnd( int fingerIndex, Vector2 fingerPos ) {&
Debug.Log("OnFingerDragEnd fingerIndex =" + fingerIndex&&+ " fingerPos ="+fingerPos); } //滑动中&&&&void OnFingerDragMove( int fingerIndex, Vector2 fingerPos, Vector2 delta )&&&&{&&&&&&&&&& transform.position = GetWorldPos( fingerPos );
Debug.Log(" OnFingerDragMove ="&&+fingerPos); &&&&&} //上下左右四方方向滑动手势操作 void OnFingerSwipe( int fingerIndex, Vector2 startPos, FingerGestures.SwipeDirection direction, float velocity )&&&&{
//结果是 Up Down Left Right 四个方向
Debug.Log("OnFingerSwipe " + direction + " with finger " + fingerIndex);&&&&&}& //连续按下事件, tapCount就是当前连续按下几次 void OnFingerTap( int fingerIndex, Vector2 fingerPos, int tapCount )&&&&{&&&&&&&&&Debug.Log("OnFingerTap " + tapCount + " times with finger " + fingerIndex);&&&&&}& //按下事件开始后调用,包括 开始 结束 持续中状态只到下次事件开始!&&&&&&&& //OnFingerStationary 事件和&&OnFingerDragMove 有一个区别。&&&&&&&& //OnFingerStationary 是手指触摸在屏幕中的事件,而OnFingerDragMove是先触摸一下然后滑动的事件。&&&&&&&& //如果你需要时时捕获手指触摸屏幕中的事件时 用OnFingerStationary 即可 void OnFingerStationaryBegin( int fingerIndex, Vector2 fingerPos ) {&
Debug.Log("OnFingerStationaryBegin " + fingerPos + " times with finger " + fingerIndex); }& void OnFingerStationary( int fingerIndex, Vector2 fingerPos, float elapsedTime ) {&
Debug.Log("OnFingerStationary " + fingerPos + " times with finger " + fingerIndex);& }& void OnFingerStationaryEnd( int fingerIndex, Vector2 fingerPos, float elapsedTime ) {&
Debug.Log("OnFingerStationaryEnd " + fingerPos + " times with finger " + fingerIndex); }& //长按事件 void OnFingerLongPress( int fingerIndex, Vector2 fingerPos ) {&
Debug.Log("OnFingerLongPress " + fingerPos ); }& //把Unity屏幕坐标换算成3D坐标&&&&Vector3 GetWorldPos( Vector2 screenPos )&&&&{&&&&&&&&Camera mainCamera = Camera.main;&&&&&&&&return mainCamera.ScreenToWorldPoint( new Vector3( screenPos.x, screenPos.y, Mathf.Abs( transform.position.z - mainCamera.transform.position.z ) ) );&&&&}}
如下图所示,用鼠标还是IOS Android触摸事件都能很好的在这个Cube上响应,大家把我的代码手动的打一遍就什么都明白了。
上面的脚本,我们是直接绑定在立方体对象上来监听它,如果你想在别的脚本监听这个立方体对象的手势操作。只需调用如下方法即可。这个方法官方封装在了SampleBase中。因为官方的例子程序脚本是继承它的,所以子类就可以直接使用父类的方法。可是SampleBase会自动初始化一个SampleUI的脚本,不想初始化这个脚本的话直接用下面方法就行,原理就是通过射线我就不过多的解释了。传递鼠标或触摸的2D坐标即可得到触摸的3D模型对象。
1234567891011
&&&&// Return the GameObject at the given screen position, or null if no valid object was found&&&&public static GameObject PickObject( Vector2 screenPos )&&&&{&&&&&&&&Ray ray = Camera.main.ScreenPointToRay( screenPos );&&&&&&&&RaycastHit hit;&&&&&&&&&if( Physics.Raycast( ray, out hit ) )&&&&&&&&&&&&return hit.collider.gameObject;&&&&&&&&&return null;&&&&}
最后大家仔细看一下官方的FingerGestures.cs脚本,所有的手势操作的事件都在这里,包括单手操作事件、双手操作事件、鼠标操作事件。
插件以及源码下载地址:
雨松MOMO祝大家学习愉快,啦啦啦。
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!Unity LineRenderer 之 从屏幕中心画Line_百度经验
&&&&&&&&&在职工作Unity LineRenderer 之 从屏幕中心画Line<div class="audio-wp audio-wp-1" data-text='Unity LineRenderer 之 从屏幕中心画LineUnity LineRenderer 之 从屏幕中心画Line。本节介绍,获取屏幕中心,转为世界坐标,然后通过射线获取LineRenderer的第二个点,从屏幕中心,向外画出一条“LineRenderer”的简单案例,具体如下' data-for=''>听语音1234567
百度经验:jingyan.baidu.comUnity LineRenderer 之 从屏幕中心画Line。本节介绍,获取屏幕中心,转为世界坐标,然后通过射线获取LineRenderer的第二个点,从屏幕中心,向外画出一条“LineRenderer”的简单案例,具体如下百度经验:jingyan.baidu.comUnityLineRenderer百度经验:jingyan.baidu.com1ScreenToWorldPoint:1)功能简述public&Vector3&ScreenToWorldPoint(Vector3&position);Transforms&position&from screen space into world space.Screenspace is defined in pixels. The bottom-left of the screen is (0,0); the right-top is (pixelWidth,pixelHeight). The z position is in world units from the camera.2LineRenderer.SetPositions:1)功能简述public void&SetPositions(Vector3[]&positions);positions:The array of positions to set.Set the positions of all vertices in the line.This method is preferred to&SetPosition&when setting all positions, as it is more efficient to set all positions using a single command than to set each position individually.END百度经验:jingyan.baidu.com1打开Unity,新建一个工程,具体如下图2在场景中,新建一个“Plane”,具体如下图3在场景中,新建一个“GameObject”,然后给“GameObject”添加“LineRenderer”组件,“LineRenderer”参数如下图,再新建一个“Material”,赋给“LineRenderer”,具体如下图4在工程中,新建一个脚本“LineRendererTest”,双击脚本或者右键“Open C# Project”打开脚本,具体如下图5在“LineRendererTest”脚本上编写代码,首先获取“LineRenderer”组件,然后获取屏幕中心点转为世界坐标,接着通过射线设置“LineRenderer”的第二个点,结合第一个点画出“LineRenderer”,具体代码和代码说明如下图6“LineRendererTest”脚本的具体内容如下:using&UnityEpublic&class&LineRendererTest&:&MonoBehaviour&{&&&&public&LineRenderer&&&&&private&Vector3&screenCenterP&&&&//&Use&this&for&initialization& & void&Start&()&{&&&&&&&&screenCenterPoint&=&Camera.main.ScreenToWorldPoint&& & & & & & (new&Vector3(Screen.width&/&2,&Screen.height&/&2,&1));& & }& &&&&&&//&Update&is&called&once&per&frame& & void&Update&()&{&&&&&&&&if&(Input.GetMouseButtonDown&(0))&{&&&&&&&&&&&&Ray&ray&=&Camera.main.ScreenPointToRay&(Input.mousePosition);& & & & & & RaycastHit&hitI& & & & & & if(Physics.Raycast&(ray,&out&hitInfo)){&&&&&&&&&&&&&&&&line.SetPositions&(new&Vector3[]{screenCenterPoint,&hitInfo.point});& & & & & & }& & & & }& & }}7脚本编译正确,回到Unity界面,把脚本赋给“MainCamera”,并“GameObject”的“LineRenderer”赋值给脚本,具体如下图8运行场景,任意点击游戏视图中的“Plane”,都会从屏幕中心到“Plane”平面点画出“LineRenderer”线,具体如下图9到此,《Unity LineRenderer 之 从屏幕中心画Line》讲解结束,谢谢END百度经验:jingyan.baidu.com您的支持,是我们不断坚持知识分享的动力,若帮到您,还请帮忙投票有得;若有疑问,请留言经验内容仅供参考,如果您需解决具体问题(尤其法律、医学等领域),建议您详细咨询相关领域专业人士。作者声明:本篇经验系本人依照真实经历原创,未经许可,谢绝转载。投票(0)已投票(0)有得(0)我有疑问(0)◆◆说说为什么给这篇经验投票吧!我为什么投票...你还可以输入500字◆◆只有签约作者及以上等级才可发有得&你还可以输入1000字◆◆如对这篇经验有疑问,可反馈给作者,经验作者会尽力为您解决!你还可以输入500字相关经验00100热门杂志第3期人生知识达人职场秘诀1033次分享第1期实现创业梦想1512次分享第1期轻松理财手册693次分享第2期晋升攻坚战453次分享第1期如何用互联网理财530次分享◆请扫描分享到朋友圈}

我要回帖

更多关于 unity 转屏幕坐标 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信