editor 阿里云 count Way.js 后台管理界面 网络营销视频 seo计费系统 jq第一个子元素 hbuilder插件 python正则 java编程入门 java运行环境配置 java搭建 javafloat java环境包 java格式化字符串 心理学与生活下载 枪神传说辅助 js轮播图代码 蓝牙测试软件 流程图工具 数独软件 蜘蛛皮肤 暗黑3挂机plusready mathcad 英雄联盟美图 php教程下载 三星开发者选项在哪 cf活动一键领取 一键系统重装 机箱散热风扇安装方向 立即执行函数 微信点击文字跳转链接 python占位符 idea插件安装 Camshift maya材质库 新世界海盗秘籍 笔记本驱动 仙剑奇侠传2修改器
当前位置: 首页 > 学习教程  > 编程语言

Visual Effect Graph魔改录

2020/10/8 20:06:11 文章标签:

欢迎参与讨论,转载请注明出处。 前言 前文提到关于粒子想实现一些东西,本篇便来还愿了。Demo使用的粒子系统并非传统的Particle System,而是基于GPU的Visual Effect Graph,下文简称VEG。   VEG的问题与近年来Unity新出的模块一…

欢迎参与讨论,转载请注明出处。

前言

前文提到关于粒子想实现一些东西,本篇便来还愿了。Demo使用的粒子系统并非传统的Particle System,而是基于GPU的Visual Effect Graph,下文简称VEG。
  VEG的问题与近年来Unity新出的模块一样:有些功能就做了个壳没下文了,我需要的光照探针功能便是如此。尽管VEG在编辑器做了支持,但实际上功能是没实现的:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SkALH4dT-1602157907416)(https://musoucrow.github.io/images/veg/0.png)]
  所幸Unity近年来的模块有个好处:开源,通过Package Manager下载的模块其本身已经是开源可修改的,若是对其进行一番研究搞不好就能自己实现想要的功能,不必再苦等官方?答案是没错的,我如愿以偿为VEG增加了三个功能,并将之开源了。

研究

1
  根据上图可以发现,VEG特效的构成实际上就是Compute Shader + 一般Shader,它们是由VEG编辑器生成的,双击可查看生成后的代码。由此可见,VEG实际上与Shader Graph差不多,都是通过编辑器进行创作,最后生成相应的代码
  由于先前的经验,这类源码的入手点自然是找到编辑器定义属性的地方。比如设置Shader效果的Output部分,顺藤摸瓜便很快找到了:
2
3
  以此类推,便找到了生成Shader的相关处:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

如此路线便打通了,以上得到了两个重要的信息:每个不同的Output类型(Quad、Cube、Mesh……)都会有对应的Shader模板,表示我们加料时也要考虑到多种类型的情况。其次是区分了LegacyUniversal两个文件夹,可见分别对应Built-in与URP管线,毕竟他们使用的Shader库并不相同。如此VEG能在老管线使用,并且在HDRP有新功能就能理解了。

接受阴影

目前对于VEG最迫切需要的功能便是接受阴影了,无论实时阴影还是光照探针,VEG目前都是没有的。好在按照上文的路线通读一番后,发现追加接受阴影还是蛮容易的。
  顺着上文继续走下去,看到了主Pass下有个名为VFXApplyColor的插入片段在各类型的主Pass都有用到,可见是通用的着色过程。那么在这里加入阴影着色正好:
7
8
在这里插入图片描述

通过搜索其他函数的出处找到了Shaders/RenderPipeline/Universal/VFXCommon.hlsl,到了这里便是熟悉的Shader编写环境了,Include的文件都是URP那套,写就完事了:

float4 VFXApplyShadow(float4 color, float3 posWS) {
    float4 shadowCoord = TransformWorldToShadowCoord(posWS);
    Light mainLight = GetMainLight(shadowCoord);

    color.rgb *= mainLight.color * mainLight.distanceAttenuation * mainLight.shadowAttenuation;

    return color;
}

当然这函数还不能直接用,根据观察其他函数还会在Shaders/VFXCommonOutput.hlsl针对VEG的环境做一层封装然后写到VFXApplyColor里即可:

float4 VFXApplyShadow(float4 color,VFX_VARYING_PS_INPUTS i)
{
    #if USE_RECEIVE_SHADOWS
        #if defined(VFX_VARYING_POSWS)
            return VFXApplyShadow(color, i.VFX_VARYING_POSWS);
        #else
            return VFXApplyShadow(color, (float3)0); //Some pipeline (LWRP) doesn't require WorldPos
        #endif
    #else
        return color;
    #endif
}

10
  当然还要提供阴影相关的multi_compile,搜索代码得知加在VFXPassForwardAdditionalPragma片段,然后就可以看效果啦:
在这里插入图片描述

在这里插入图片描述

光照探针

接受实时阴影算是完成了,但还要考虑到烘焙阴影的情况,于是对于光照探针的支持也要考虑到。VEG关于光照探针的外围支持已经完备(根据光照设置、探针设置开启相关KEYWORD),欠缺的只是Shader相关的部分。
  在不考虑GI,按照我在模型渲染一样的做法的前提下,只需要在VFXApplyShadow加点料即可:

float4 VFXApplyShadow(float4 color, float3 posWS) {
    float4 shadowCoord = TransformWorldToShadowCoord(posWS);
    Light mainLight = GetMainLight(shadowCoord);

#if defined(_MIXED_LIGHTING_SUBTRACTIVE)
    mainLight.distanceAttenuation = lerp(GetMainLightShadowStrength(), 1, saturate(mainLight.distanceAttenuation));
#endif

    color.rgb *= mainLight.color * mainLight.distanceAttenuation * mainLight.shadowAttenuation;

    return color;
}

与之前的做法一样,distanceAttenuation在光照探针下会变成光照计算的着色值,将之锁定在阴影强度-1之间即可。然后烘焙阴影,设置特效组件开启光照探针即可看到效果了:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9iRGnIlV-1602157907424)(https://musoucrow.github.io/images/veg/13.gif)]
  比较遗憾的是,光照探针的计算是以GameObject为准的,而非以每个粒子为准,这也是没办法的事,只能尽量避免露馅了。
  关于阴影还剩最后一个点没有做:在编辑器的开关设置,这个模仿其他属性添加变量,并在VFXParticleOutput.csadditionalDefines变量里添加相关KEYWORD,最后在Shader里做判定即可:
14
在这里插入图片描述

水面问题

目前粒子特效在水面上显示会出现很明显的层次错误:
16
  火焰实际上并没有进入水里,但是看着却变蓝了。这是因为水面的渲染时机在所有对象之后,并使用CameraColorTexture进行显示。而此时火焰已在Texture里了,于是与水重叠的部分便被水渲染处理了。
  基于这个问题可以很迅速的想到解法:利用RenderFeature的RenderObjects可以新建渲染批次,并将粒子主Pass的LightMode改为新的批次即可:
在这里插入图片描述

在这里插入图片描述

试了下效果,问题的确解决了,但是……
19
  但是水里的火焰消失了,这也是当然的,毕竟在水面渲染之前,火焰还没渲染呢。进一步思考后想到了个绝妙的方案:为粒子新增一个与主Pass一模一样的Pass,也就是目前的ParticlePost,保留原本的主Pass,将LightMode还原。当然只是如此的话会出现一个粒子渲染两次重叠起来的情况,而我们可以让ParticlePost只在与水面重叠时显示,这样便可解决重叠问题了。
  为此我们要用上模板测试,让水面写入特定的模板值,然后在ParticlePost做判定(假设水面写入值为2):
在这里插入图片描述

限于篇幅,关于添加Pass的做法还请自行查阅源码。看看效果吧:
在这里插入图片描述

很棒很棒,这下算是解决粒子与水面的问题了。尽管在水面时事实上是有重叠的,看着效果还行就凑合吧。由此延伸可以说是半透明对象与水面的一种解决方案了。
  最后是编辑器相关,只能写死数值显然是不好的,这里我使用了VEG提供的定义代码段功能,在VFXParticleOutput.csadditionalReplacements变量添加,并在模板里调用即可:
在这里插入图片描述

23

后记

VEG较之传统粒子最大的优势便是运算放在GPU以及开放源码可供修改了吧,可惜必须在支持Compute Shader的设备上才能运作。这一点注定它在手游里很难用得上了,只能期待老手机早日淘汰了……


本文链接: http://www.dtmao.cc/news_show_250192.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?