Unity URP中的多Pass Shader和Planer shadow

一 .Unity移动端软阴影技术总结:

https://blog.csdn.net/jxw167/article/details/82422891

二. 平面阴影的原理

https://zhuanlan.zhihu.com/p/42781261

https://zhuanlan.zhihu.com/p/31504088

王者荣耀游戏使用的就是该方法,已经有上线产品验证过的方法,这说明我们的游戏产品也可以使用,该技术叫平面投影阴影(Planar Projected Shadows)技术,由Jim Blinn 1988年提出。http://www.twinklingstar.cn/2015/1717/tech-of-shadows/#21_Blinns
它实现的原理是:通过相似三角形求一个物体每一个顶点在某个平面上的投影位置,说白了就是求直线在平面上的交点。进一步通俗点讲:物体上的某一点,以直线光源的方向作为方向,从该点出发,移动一定距离,使得该点落在要显示阴影的平面上(比如地表),随后将该点显示为阴影即可。

建议大家在平时可以阅读一下几个比较好的会议论文:GDC系列文章和Siggraph系列文章,这个两个会议的论文都是代表当前比较超前的算法实现,这些算法我们可以将其用Unity或者UE4其他引擎实现出来增加渲染效果。

线段与平面的交点推导(很重要):

 

 三. 平面阴影的实现

1.第一个pass正常渲染物体,根据各项目的需求实现(跟阴影实现无关)

2.另一个pass渲染该物体的阴影

阴影pass的实现:

1.从C#脚本中传入Shader需要投影的平面及一些相关信息

public Light mainLight;private Vector4 _ShadowFadeParams = new Vector4(0.0f, 1.5f, 0.7f, 0.0f);private void UpdateShader(){Vector4 worldpos = transform.position;Vector3 shadowPlaneNrm = transform.up;//计算平面法线与平面上某一点的点乘,由于人物行走在平面上,人物脚下的点必定在平面上float nrmDotPos = Vector3.Dot(shadowPlaneNrm, worldpos);// Vector4 projdir = new Vector4(-0.2f,-0.8f,-0.6f,0);Vector4 projdir = mainLight.transform.forward;//Debug.Log("projdir" + projdir);Material mat = Renderer.material;//   foreach (var mat in mMatList)//   {if (mat == null)return;mat.SetVector("_WorldPos", worldpos);mat.SetVector("_ShadowProjDir", projdir);//  mat.SetVector("_ShadowPlane", new Vector4(2.289143f, -11.88877f, 28.79983f, 0.0f));mat.SetVector("_ShadowPlane", new Vector4(shadowPlaneNrm.x, shadowPlaneNrm.y, shadowPlaneNrm.z, nrmDotPos));mat.SetVector("_ShadowFadeParams", _ShadowFadeParams);mat.SetFloat("_ShadowFalloff", 1.35f);//  }}

2.顶点Shader计算该点在阴影平面的投影

			v2f vert(appdata v){v2f o;float3 lightdir = normalize(_ShadowProjDir);float3 worldpos = mul(unity_ObjectToWorld, v.vertex).xyz;// _ShadowPlane.w = p0 * n  // 平面的w分量就是p0 * nfloat distance = (_ShadowPlane.w - dot(_ShadowPlane.xyz, worldpos)) / dot(_ShadowPlane.xyz, lightdir.xyz);worldpos = worldpos + distance * lightdir.xyz;o.vertex = mul(unity_MatrixVP, float4(worldpos, 1.0));o.xlv_TEXCOORD0 = _WorldPos.xyz;o.xlv_TEXCOORD1 = worldpos;return o;}

3.片段Shader进行模糊算法等处理,改善阴影效果

	float4 frag(v2f i) : SV_Target{float3 posToPlane_2 = (i.xlv_TEXCOORD0 - i.xlv_TEXCOORD1);float4 color;color.xyz = float3(0.0, 0.0, 0.0);// 下面两种阴影衰减公式都可以使用(当然也可以自己写衰减公式)// 王者荣耀的衰减公式color.w = (pow((1.0 - clamp(((sqrt(dot(posToPlane_2, posToPlane_2)) * _ShadowInvLen) - _ShadowFadeParams.x), 0.0, 1.0)), _ShadowFadeParams.y) * _ShadowFadeParams.z);// 另外的阴影衰减公式//color.w = 1.0 - saturate(distance(i.xlv_TEXCOORD0, i.xlv_TEXCOORD1) * _ShadowFalloff);return color;}

其中计算核心的两行代码就是 

float distance = (_ShadowPlane.w - dot(_ShadowPlane.xyz, worldpos)) / dot(_ShadowPlane.xyz, lightdir.xyz);
worldpos = worldpos + distance * lightdir.xyz;

对应的公式就是下式,其中P0和平面法线的点乘是由C#代码计算后传入的,存储在_ShadowPlane的w分量(如果平面是水平的,即法线方向就是y轴的话, _ShadowPlane的w分量可以直接传入的是平面的y值)

 

 

四. 平面阴影在URP中的实现

URP中常规渲染是单Pass渲染,平面shadow需要两个pass,为了实现平面shadow,需要先解决URP中的两个Pass渲染。

https://blog.csdn.net/nxl76450106/article/details/101290283

在需要执行的第一个pass添加Tags{ "LightMode" = "LightweightForward(或者UniversalForward,或者Universal2D,根据当前正常渲染时使用的render设置)" },第二个pass添加Tags{ "LightMode" = "SRPDefaultUnlit" }即可让这两个pass同时生效。

比如我们项目目前用的是Universal2D渲染,即2D的光照渲染,就需要把第一个Pass的Tag设置为Universal2D,此时你会发现如果camera使用的Render不是Universal2D render,就无法渲染出物体。所以总结来讲就是camera使用的Render要和Pass中的Tag对应。

解决两个Pass渲染问题后,第一个pass我直接copy URP内置的SimpleLit函数的光照Pass,第二个Pass用HLSL语言重写了上边的CG语言代码,替换了几处API:

			Pass{Tags{"LightMode" = "SRPDefaultUnlit"}Blend SrcAlpha  OneMinusSrcAlphaZWrite OffCull BackColorMask RGBStencil{Ref 0Comp EqualWriteMask 255ReadMask 255//Pass IncrSatPass InvertFail KeepZFail Keep}//CGPROGRAMHLSLPROGRAM#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"#pragma vertex vert#pragma fragment fragCBUFFER_START(UnityPerFrame)float4x4 unity_MatrixVP;CBUFFER_ENDCBUFFER_START(UnityPerDraw)float4x4 unity_ObjectToWorld;CBUFFER_END#define UNITY_MATRIX_M unity_ObjectToWorldfloat4 _ShadowPlane;float4 _ShadowProjDir;float4 _WorldPos;float _ShadowInvLen;float4 _ShadowFadeParams;float _ShadowFalloff;struct appdata{float4 vertex : POSITION;};struct v2f{float4 vertex : SV_POSITION;float3 xlv_TEXCOORD0 : TEXCOORD0;float3 xlv_TEXCOORD1 : TEXCOORD1;};v2f vert(appdata v){v2f o;float3 lightdir = normalize(_ShadowProjDir);//float3 worldpos = mul(unity_ObjectToWorld, v.vertex).xyz;//float3 worldpos = TransformObjectToWorld(v.vertex.xyz);float4 worldPos = mul(UNITY_MATRIX_M, float4(v.vertex.xyz, 1.0));// _ShadowPlane.w = p0 * n  // 平面的w分量就是p0 * nfloat distance = (_ShadowPlane.w - dot(_ShadowPlane.xyz, worldPos.xyz)) / dot(_ShadowPlane.xyz, lightdir.xyz);worldPos = worldPos + distance * float4(lightdir.xyz, 0.0);//o.vertex = mul(unity_MatrixVP, float4(worldpos, 1.0));//o.vertex = TransformWorldToHClip(float4(worldpos, 1.0));o.vertex = mul(unity_MatrixVP, worldPos);o.xlv_TEXCOORD0 = _WorldPos.xyz;o.xlv_TEXCOORD1 = worldPos;return o;}float4 frag(v2f i) : SV_Target{float3 posToPlane_2 = (i.xlv_TEXCOORD0 - i.xlv_TEXCOORD1);float4 color;color.xyz = float3(0.0, 0.0, 0.0);// 下面两种阴影衰减公式都可以使用(当然也可以自己写衰减公式)// 王者荣耀的衰减公式color.w = (pow((1.0 - clamp(((sqrt(dot(posToPlane_2, posToPlane_2)) * _ShadowInvLen) - _ShadowFadeParams.x), 0.0, 1.0)), _ShadowFadeParams.y) * _ShadowFadeParams.z);// 另外的阴影衰减公式//color.w = 1.0 - saturate(distance(i.xlv_TEXCOORD0, i.xlv_TEXCOORD1) * _ShadowFalloff);return color;}//ENDCGENDHLSL}

项目链接:

https://github.com/Dejavu0709/Plane-Shadow-For-URP.git

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246117.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java连接mongodb_第78天: Python 操作 MongoDB 数据库介绍

MongoDB 是一款面向文档型的 NoSQL 数据库,是一个基于分布式文件存储的开源的非关系型数据库系统,其内容是以 K/V 形式存储,结构不固定,它的字段值可以包含其他文档、数组和文档数组等。其采用的 BSON(二进制 JSON )的数据结构&am…

URP中的2D Light光照在移动端不生效的问题

最近在尝试用URP推出的还在preview阶段的2D Render系统,发现2D光照在打成APK后失效,尝试了些方法后发现把2d光照用到的shader放进设置中的built in shader后可以解决问题:

大连开发区取暖费能微信支付吗_下半年教资报考人数增加,那到底能不能异地报考呢?...

想要每周获取两篇群文件快扫码进群吧~因为教师资格证认定的问题,最近教师资格证备考又被广大考生提上了日程,由于“先上岗,后考证”政策,小编预测下一年教师资格证考试的通过率肯定没有以前那么高了,不少人就想选择异地…

python3项目源代码下载_2019年最值得关注的34个Python开源项目——Let's go!

踏着人工智能、区块链的东风,近年来一路“横冲直撞”的 Python 在实现了从小众语言到主流的完美转身后,一头扎进了 2019,依旧没有透出丝毫停下来的架势,反倒有些越烧越热的味道。本文将为你介绍 2019 年最值得关注的 34 个 Python…

Unity 音频优化方案

参考资料: https://www.cnblogs.com/bearhb/p/11210136.html https://blog.csdn.net/chenfujun818/article/details/81710895 文件格式 mp3:失真小,适合音质要求高的文件,例如BGM wav:资源大,不推荐 ogg:压缩比高,适…

android home键后计时拉起app_使用React Native完成App软件

搭建开发环境安装react-native-cli:npm i -g react-native-cliAndroid SDK安装Android SDK并启动进行配置:配置环境变量export ANDROID_HOME~/Library/Android/sdk export PATH${PATH}:${ANDROID_HOME}/tools export PATH${PATH}:${ANDROID_HOME}/platfo…

Unity AssetBundle内存管理相关问题

AssetBundle机制相关资料收集 最近网友通过网站搜索Unity3D在手机及其他平台下占用内存太大. 这里写下关于Unity3D对于内存的管理与优化. Unity3D 里有两种动态加载机制:一个是Resources.Load,另外一个通过AssetBundle,其实两者区别不大。 Resources.L…

移动超级sim卡 无法下载卡_中国移动发布超级SIM卡:全变了

近日,中国移动正式公布了《中国移动超级SIM卡技术白皮书》,明确乐中国移动对于个人领域SIM卡的发展方向、架构设计、能力要求,旨在为行业规划设计SIM卡相关技术、产品和解决方案时提供参考和指引。据悉,中国移动的超级SIM卡增强了…

echart中拆线点的偏移_Qt中圆弧和扇形的绘制

在超声软件的开发中,超声成像模块需要绘制圆弧,例如绘制一个扇形的取样框,左右是一条直线,上下是一个圆弧,像这样。Qt中使用QPainter::drawArc绘制圆弧,使用QPainter::drawPie绘制扇形。圆弧和扇形的绘制接…

python xpath定位元素方法_Python爬虫杂记 - Xpath高级用法

xpath 高级用法 1. 匹配当前节点下的所有: .// . 表示当前 // 表示当前标签下的所有标签 注: 要配合使用 2. 匹配某标签的属性值: /属性名称 这里以input里的value值为例: 例:xpath(//input/value) 3. 匹配多个路径&am…

反向Z(Reversed-Z)的深度缓冲原理

参考文章:https://zhuanlan.zhihu.com/p/75517534 https://zjinc36.github.io/2020/03/10/2020-20200309-%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E6%B5%AE%E7%82%B9%E6%95%B0%E4%B8%8E%E6%B5%AE%E7%82%B9%E6%95%B0%E7%9A%84%E7%B2%BE%E5%BA%A6%E9%97%AE%E9%A2%98/ …

screenocr怎么卸载_screenocr是什么软件 screenocr软件及其功能介绍

在日常的生活和工作当中不免会遇到一些无法进行复制但是又想要去将它摘录下来的文字。用手去进行输入的话及麻烦又费力,这个时候我们可以使用OCR技术来讲它们识别出来。而screenocr就是这样子的一款软件,还不是很了解screenocr都有哪些功能如何使用的用户…

saspython知乎_SAS入门书籍有哪些值得推荐?

2020年 8月更新:我觉得,我应该推荐下我本人出版的《SAS编程演义》《SAS编程演义》(谷鸿秋)【摘要 书评 试读】- 京东图书​item.jd.com ------------------------------------------------------------ 我觉得这个问题我还是可以唠叨几句的,我…

access exex控制pc_ownCloud/Nextcloud文件访问控制(Files Access Control)

事实上这是一个插件(APP),也是ownCloud/Nextcloud的一项重要功能:文件访问控制。文件访问控制APP可以提供丰富强大的访问管理功能,从单文件权限到组文件,再到IP地址屏蔽,可以引用访问的时间、文件类型、用户、组等因素…

渲染杂谈:early-z、z-culling、hi-z、z-perpass到底是什么?

渲染杂谈:early-z、z-culling、hi-z、z-perpass到底是什么? 之前一直被这几个和深度缓存(z-buffer)相关的概念搞得神魂颠倒。今天在翻阅《Real-Time Rendering》时碰巧碰巧看到了这部分的讲解。硬着头皮看了看,姑且算…

output怎么用_性能领先,即训即用,快速部署,飞桨首次揭秘服务器端推理库

允中 发自 凹非寺量子位 编辑 | 公众号 QbitAI假如问在深度学习实践中,最难的部分是什么?猜测80%的开发者都会说:“当然是调参啊。”为什么难呢?因为调参就像厨师根据食材找到了料理配方,药剂师根据药材找到了药方&…

GPU架构杂乱备忘——IMR、TBR、TBDR

原文:https://juejin.cn/post/6844904132864655367 GPU架构杂乱备忘——IMR、TBR、TBDR 之前觉得涉及到gpu架构相关的问题只需要知道个大概就好,毕竟在图形api的层面上应该把硬件的细节给隐蔽掉,gpu的架构千千万万,每家厂商每个…

如何用python制作九九乘法表_Python一行代码给儿子制作九九乘法表

一行代码实现九九乘法表 print(\n.join( .join([%sX%s%s%(j,i,i*j) for j in range(1,i1)]) for i in range(1,10))) 1X11 1X22 2X24 1X33 2X36 3X39 1X44 2X48 3X412 4X416 1X55 2X510 3X515 4X520 5X525 1X66 2X612 3X618 4X624 5X630 6X636 1X77 2X714 3X721 4X728 5X735 6X…

帧同步相关文章

https://zentia.github.io/2019/04/22/frame-sync/ http://www.skywind.me/blog/archives/131 https://blog.codingnow.com/2018/08/lockstep.html

动词变名词的变化规则_动词过去式变化规则 - 点评英语网

动词考查是英语学习的重点和难点,动词过去式和过去分词的变化是学生学习的“拦路虎“之一。为了避免枯燥的去记忆,我们可以用一些轻松有趣的口诀去记住动词过去式的变化形式。动词过去式的变化口诀过去式很简单,只要你能这样记。前提必须是动…