[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 作者:毛星云(浅墨) ...
随机推荐
- sublime Text3 设置用新标签页打开新的文件
今天用sublime Text3 打开项目文件,发现单击文件就可以打开,但是有一个问题:每次打开新文件就会覆盖当前的标签页,无法在新的标签页打开.于是在网上查了一下. 网上有人说在Preference ...
- linux 安装 bitnamid-redmine
Unix 和 Linux 安装 Perl Unix/Linux 系统上 Perl 安装步骤如下: 通过浏览器打开 http://www.perl.org/get.html. 下载适用于 Unix/Li ...
- 第26天:js-$id函数、焦点事件
一.函数return语句定义函数的返回值,在函数内部用return来设置返回值,一个函数只能有一个返回值.同时,终止代码的执行.所有自定义函数默认没有返回值return后面不要换行 var a=10, ...
- 【.Net】C#实现多线程的方式:使用Parallel类
简介 在C#中实现多线程的另一个方式是使用Parallel类. 在.NET4中 ,另一个新增的抽象线程是Parallel类 .这个类定义了并行的for和foreach的 静态方法.在为 for和 f ...
- [luogu3806]【模板】点分治1
description 求树上长度为\(k\)的路径是否存在. data range \[n\le 10000,k\le 10000000\] solution 点分治复习... 使用普通的点分治枚举 ...
- [UVA307]小木棍 Sticks
题目大意:有一堆小木棍,把它们接成相同长度的小木棍,问结果的小木棍的最小长度是多少,多组数据 题解:$dfs$,各种剪枝. 卡点:无 C++ Code: #include <cstdio> ...
- [LOJ #6433]「PKUSC2018」最大前缀和
题目大意:给你一个$n(n\leqslant20)$项的数列$A$,设重排后的数列为$A'$,令$pre_p=\sum\limits_{i=1}^pA'_i$,求$max\{pre_i\}$的期望,乘 ...
- Android <Android应用开发实战> 学习总结杂项
1.系统相册默认保存地址:android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM/Ca ...
- POJ1651:Multiplication Puzzle——题解
http://poj.org/problem?id=1651 题目大意:同“乘法游戏”,这里将乘法游戏的题面复制过来. 乘法游戏是在一行牌上进行的.每一张牌包括了一个正整数.在每一个移动中,玩家拿出一 ...
- BZOJ5300:[CQOI2018]九连环——题解
一种打表的方法,适用于知道如何解九连环的人. 我们知道,解九(n)连环必须先解第九(n)环,然后解八(n-1).七(n-2)-- 根据这个我们飞快的写出了一个递推式,设\(f[i]\)为\(i\)连环 ...