[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 作者:毛星云(浅墨) ...
随机推荐
- 数论的欧拉定理证明 & 欧拉函数公式(转载)
欧拉函数 :欧拉函数是数论中很重要的一个函数,欧拉函数是指:对于一个正整数 n ,小于 n 且和 n 互质的正整数(包括 1)的个数,记作 φ(n) . 完全余数集合:定义小于 n 且和 n 互质的数 ...
- try catch finally 与continue的使用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- opencv里vector的内存的申请和释放的问题
改成: ); CvSeq * m_contour=; cvFindContours( &IPlImage(img), m_storage, &m_contour, ,)); //释放内 ...
- dwarf是如何处理栈帧的?
dwarf是如何处理栈帧的? DW_AT_frame_base 表明函数栈帧的起始点 95 < 1><0x000000ca> DW_TAG_subprogram 96 ...
- Java 多线程 三种实现方式
Java多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没 ...
- Android Studio类中实现Serializable自动生成serialVersionUID
1.File -> Settings... -> Editor -> Inspections -> Serialization issues -> Serializabl ...
- 【bzoj1858】[Scoi2010]序列操作 线段树区间合并
题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...
- bzoj1208: [HNOI2004]宠物收养所 (sbt)
切傻逼题还能wa那么多次我也是醉了 好啦其实是sbt都不会敲了(一直用神器treap) 重点是研究了下陈大神的删除,以前treap的删除都是直接旋转去删的…… 还是treap大法好&…… 题解 ...
- [TJOI2013]最长上升子序列 平衡树
其实是一道性质题. 首先观察到插入的数是递增的, 那么根据上升子序列的性质, 我们的非法情况就是统计到了在一个数前面的后插入的数, 但是由于插入的数是递增的,显然插入这个数后,这个数就是最大的,所以除 ...
- redux的bindActionCreators
bindActionCreators是redux的一个API,作用是将单个或多个ActionCreator转化为dispatch(action)的函数集合形式. 开发者不用再手动dispatch(ac ...