[Unity]在Shader中获取摄像机角度、视线的问题
又踩了一坑,好在谷歌到了之前的一个人遇到相同的问题,顺利解决。
先说说问题背景,我目前的毕设是体数据渲染,实现的办法是raycast。最基本的一点就是在fragment program里,获取raycast的方向。
问题出现在加入阴影之后。在这之前,获取方向是没问题的。
在透视相机中,可以简单地用float3 viewDir = normalize(worldPos - _WorldSpaceCameraPos);来获取方向。
在正交相机中,我们需要换个方法,来获取相机的朝向(对正交相机来说,朝向就是raycast的方向)。Unity提供了一个参数来表示当前相机的类型。

因此我们可以用这样的式子替换,来适应两种相机
float3 viewDir =
unity_OrthoParams.w * -UNITY_MATRIX_V[2].xyz //这个-UNITY_MATRIX_V[2].xyz可以用来表示相机的朝向,即C#代码里的transform.forward
+
(1- unity_OrthoParams.w) * (worldPos - _WorldSpaceCameraPos);
这个时候我用常规的办法加入了阴影(引入ShadowCaster的pass)。并且用同样的办法计算深度然后输出。然后……就出问题了,主要表现是在Shadow Map里渲染错位。
一番排查之后发现了问题。目前我只考虑单个Directional Light,下面也都按照Directional Light来说。按照Shadow Map的流程,我们会需要Directional Light为相机渲染一次Shadow Map。此时该Light相当于一个正交相机。尽管之前我们对两种相机都做了适应,但是……在渲染ShadowMap的时候,这个unity_OrthoParams,是不管用的,因此viewDir的计算是按照透视相机来的,于是就错位了。
所以我们得自己判断正交还是透视了。好在有大神给出了解答:使用UNITY_MATRIX_P[3][3] 进行判断。为0表示透视,1表示正交。具体原理我也不清楚,不过测试之后是完全可行的。
修改后的viewDir如下:
float3 viewDir = normalize(
UNITY_MATRIX_P[3][3] * -UNITY_MATRIX_V[2].xyz
+
(1 - UNITY_MATRIX_P[3][3]) * (worldPos - _WorldSpaceCameraPos));
另外推荐一个系列教程:http://catlikecoding.com/unity/tutorials/ 其中包括了shader编程,由浅入深地把unity5的standard surface shader复现了一遍,包括编辑器界面。同时包括了各种技术的原理、实现。看一遍绝对是受益颇多。除开shader的教程,其他的几个教程也是非常有意思。总之强烈推荐。
[Unity]在Shader中获取摄像机角度、视线的问题的更多相关文章
- Unity关闭shader中的光照模型以及如何自定义光照模型
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject' // Upgrade NOTE: replaced '_Wor ...
- 【Unity Shaders】Shader中的光照
写在前面 自己写过Vertex & Fragment Shader的童鞋,大概都会对Unity的光照痛恨不已.当然,我相信这是因为我们写得少...不过这也是由于官方文档对这方面介绍很少的缘故, ...
- 不能直接获取?聊聊如何在Shader Graph中获取深度图
0x00 前言 在这篇文章中,我们选择了过去几周Unity官方社区交流群以及UUG社区群中比较有代表性的几个问题,总结在这里和大家进行分享.主要涵盖了** StreamingAssets.Profil ...
- Unity 基于Cinemachine计算透视摄像机在地图中的移动范围
Unity中Cinemachine的基础功能介绍可详见之前写的博客: https://www.cnblogs.com/koshio0219/p/11820654.html 本篇的重点是讨论,在给定规则 ...
- 【Unity Shaders】Diffuse Shading——在Surface Shader中使用properties
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- unity, multi pass shader中的surface pass
今天尝试写一个multi pass shader,但其中有一个Pass是surface pass,总是莫名奇妙地报错.后来看到下面帖子: http://forum.unity3d.com/thread ...
- unity, shader中获得当前像素深度
frag shader中直接访问i.pos.z就是深度,不必除以i.pos.w,因为系统已经自动进行过了透视除法且已将i.pos.w置为0.
- Unity小知识---第三人称中设置摄像机的简单跟随
第三人称中设置摄像机的简单跟随 private Transform player; private Vector3 offect; private float smooothing = 3f; //插 ...
- 【淡墨Unity3D Shader计划】五 圣诞用品: Unity在Shader三种形式的控制&混合操作编译
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/42060963 作者:毛星云(浅墨) ...
随机推荐
- Debian 7 amd64 + fbterm + ucimf
前段时间,显示器出了问题,导致Debian下只有终端显示正常,桌面显示效果很是摇晃模糊.遂起了念头,能不能在终端下就能完成日常的工作. google了很久,终于知道fbterm可以在终端下显示中文,加 ...
- position定位-absolute与fixed
1. absolute 生成绝对定位元素,相对于static定位以外的第一个父元素进行定位. 2. fixed 生成绝对定位元素,相对于浏览器窗口进行定位.
- Firefox火狐浏览器 修改默认搜索引擎
如图:
- MySQL中使用trim()删除两侧字符
在某些情况下由于程序没处理好,导致数据表中有些字段的值会有空白字符出现,如 这样如果在严格比对name时会匹配不到.trim()函数可以解决这样的问题 作为trim()函数的子集,ltrim()函数是 ...
- 再看RCU
从昨天晚上开始,我就立志要把RCU拿下,昨晚加今天早上看了RCU的东西,太细节的原理我就不扣了,放弃,知道RCU是怎么用的就可以了,赶紧看文件系统中dcache的管理了. 说说RCU,RCU其实是很简 ...
- MAC锁屏不断网(快捷键启用屏保)
第一步:要设定锁定输入密码的设置,进入'系统偏好设置''安全性与隐私',将选项'进入睡眠或开始屏幕保护程序后'打勾,选'立即'. 第二步:到'launchpad'中的'其他'文件夹打开'Automat ...
- wpf DataGrid加载行号
<DataGrid Name="tkdg" HorizontalContentAlignment="Center" AutoGenerateColumns ...
- matlab imwrite
函数功能:将图像数据写入到图像文件中,存储在磁盘上. 调用格式:imwrite(A,filename,fmt) A是图像数据,filename是目标图像名字,fmt是要生成的图片的格式. 图片格式有: ...
- 【bzoj3631】[JLOI2014]松鼠的新家 LCA+差分数组
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀请小熊维尼前来 ...
- Javascript基础之-强制类型转换(二)
思考下面这个问题: console.log(+"123"); // 123 console.log(-"123"); // -123 console.log(+ ...