赞
踩
这一方法参考自连接里的“粒子”方法。
思路是将粒子结果绘制进一张RT中,在屏幕上去采样这张RT作为dir扰动信息扰动屏幕画面。(粒子贴一张圆形法线图)
public class RainDrop : ScriptableRendererFeature { [Serializable] public class Setting { public Material material; public float _normalIntensity; [Range(0,4)]public float downSample; } public bool enable = false; public Setting setting = new Setting(); public RainPass rainPass; public override void Create() { rainPass = new RainPass(); } public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if(!enable ) return; rainPass.SetUp(setting, renderer.cameraColorTarget); renderer.EnqueuePass(rainPass); } } public class RainPass : ScriptableRenderPass { public RainDrop.Setting setting; //传递进来的屏幕ColorRT public RenderTargetIdentifier colRT; //绘制particle的pass名称 ShaderTagId PtagId = new ShaderTagId("ParticleNormalMap"); //particle的ColorRT private RenderTexture ParticleRt; public RainPass() { //绘制事件在后效之前 renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing; } //过滤设置: 半透明队列里的effect层 FilteringSettings _filteringSettings = new FilteringSettings(RenderQueueRange.transparent, layerMask:LayerMask.GetMask("Effect")); public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { var material = setting.material; if (material == null || material.shader == null || !material.shader.isSupported) return; //屏幕雨滴buffer CommandBuffer cmd = CommandBufferPool.Get("ScreenRain"); cmd.Clear(); //绘制设置: pass, renderingData, 半透明类, DrawingSettings drawingSettings = CreateDrawingSettings(PtagId, ref renderingData, SortingCriteria.CommonTransparent); //根据调用,绘制设置,过滤设置 ref是为了在不同状态更新时复用drawRenderer context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref _filteringSettings); //设置绘制的贴图给全局变量 用以后面作为扰动源 Shader.SetGlobalTexture("_ParticleNormalTex", ParticleRt); //屏幕画面 var descriptor = renderingData.cameraData.cameraTargetDescriptor; descriptor.msaaSamples = 1; descriptor.depthBufferBits = 0; var texId = Shader.PropertyToID("_ScreenRain"); cmd.GetTemporaryRT(texId, descriptor); material.SetFloat("_NormalIntensity", setting._normalIntensity); //把shader 0 pass内容根据传递进来的屏幕colorRT绘制到我们的_ScreenRain图上 cmd.Blit(colRT, texId, material, 0); //将_ScreenRain图复制回屏幕colorRT,这一步是因为我们不能边读边写屏幕colorRT cmd.Blit(texId, colRT); //释放我们的临时RT cmd.ReleaseTemporaryRT(texId); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } public void SetUp(RainDrop.Setting setting, RenderTargetIdentifier rendererCameraColorTarget) { this.setting = setting; //传递屏幕colorRT进Pass里 colRT = rendererCameraColorTarget; } public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { if (!ParticleRt) { //粒子colorRT 做降采样 ParticleRt = new RenderTexture(512>>(int)setting.downSample, 512 >> (int)setting.downSample, 0); ParticleRt.Create(); ParticleRt.name = "_ParticalRTNormal"; } //绘制目标 ConfigureTarget(ParticleRt); //绘制外内容设置为灰,我们为了过滤精度问题将a通道设置为0在pass中使用 ConfigureClear(ClearFlag.All, new Color(0.5f,0.5f,0.5f,0f)); } }
Shader //TODO { Properties { _MainTex ("Texture", 2D) = "white" {} _NormalIntensity("NormalIntensity",Float) = 1 } SubShader { Pass { name "Forward" Tags { "LightMode" = "ScreenRain" } ZWrite off ZTest Always half4 frag(Varyings input) : SV_Target { // sample the texture //normaltex是一张非sRGB的2d线性图 half4 normalVector = tex2D(_ParticleNormalTex, input.uv); //手动unpack float3 normalDir = normalVector * 2 - 1; //乘以我们涂白部分就是只有白色部分会影响屏幕 normalDir.xy *= _NormalIntensity * normalVector.a; //扰动屏幕画面 float2 uv = input.uv + normalDir.xy; half4 col = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, uv); return half4(col.rgb, 1); } ENDHLSL } Pass{ name "particle normal map" Tags { "LightMode" = "ParticleNormalMap" } Blend One One ColorMask RGBA Cull Off Lighting Off ZWrite Off half4 frag(Varyings input) : SV_Target { // sample the texture half4 col = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, input.uv); col.a = 1;//因为RenderFeature中我们将绘制信息外涂黑为0,所以有内容部分涂白为1 return col; } ENDHLSL } } }
大功告成,接下来就是看粒子效果怎么调整像水滴了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。