当前位置:   article > 正文

【Unity】2019 HDRP 7.3 CustomPass 高斯模糊_unity hdrp 图片 高斯模糊

unity hdrp 图片 高斯模糊

2021HDRP模糊效果Demo git参考:

GitHub - alelievr/HDRP-Custom-Passes: A bunch of custom passes made for HDRP

1、创建HDRP项目 

2、创建CustomPass物体

新增2个FullScreenCustomPass

 

创建一个OutlineH材质球和OutlineH着色器,将OutlineH着色器拖拽给OutlineH材质球,OutlineH着色器代码如下:

  1. Shader "Hidden/OutlineH"
  2. {
  3. Properties{
  4. _BlurScale("BlurScale", float) = 1
  5. }
  6. HLSLINCLUDE
  7. #pragma vertex Vert
  8. #pragma target 4.5
  9. #pragma only_renderers d3d11 playstation xboxone vulkan metal switch
  10. #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl"
  11. float _BlurScale;
  12. float2 ClampUVs(float2 uv)
  13. {
  14. uv = clamp(uv, 0, _RTHandleScale.xy - _ScreenSize.zw * 2); // clamp UV to 1 pixel to avoid bleeding
  15. return uv;
  16. }
  17. float2 GetSampleUVs(Varyings varyings)
  18. {
  19. float depth = LoadCameraDepth(varyings.positionCS.xy);
  20. PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
  21. return posInput.positionNDC.xy * _RTHandleScale.xy;
  22. }
  23. float4 FullScreenPass(Varyings varyings) : SV_Target
  24. {
  25. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
  26. float depth = LoadCameraDepth(varyings.positionCS.xy);
  27. PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
  28. float4 color = float4(0.0, 0.0, 0.0, 0.0);
  29. // Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
  30. if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING)
  31. color = float4(CustomPassSampleCameraColor(posInput.positionNDC.xy, 0), 1);
  32. //UV获取方式,varyings.positionCS.xy * _ScreenSize.zw为NDC坐标,_RTHandleScale.xy是对NDC坐标进行一个缩放获取uv
  33. //float2 uv = ClampUVs(varyings.positionCS.xy * _ScreenSize.zw * _RTHandleScale.xy);
  34. //横向模糊(需要起另一个CustomPass处理纵向模糊)
  35. float3 sumColor = 0;
  36. float weight[3] = { 0.4026, 0.2442, 0.0545 };
  37. sumColor = color.rgb * weight[0];
  38. for (int i = 1; i < 3; i++)
  39. {
  40. //注意因为采样坐标是用NDC坐标,故float2(_BlurScale * i, 0) * _ScreenSize.zw是获取一个NDC坐标系上的增量(偏移值) 进行对周围横向或纵向像素采样!
  41. sumColor += CustomPassSampleCameraColor(posInput.positionNDC.xy + float2(_BlurScale * i, 0) * _ScreenSize.zw, 0).rgb * weight[i];
  42. sumColor += CustomPassSampleCameraColor(posInput.positionNDC.xy + float2(_BlurScale * -i, 0) * _ScreenSize.zw, 0).rgb * weight[i];
  43. }
  44. return float4(sumColor, 1);
  45. }
  46. ENDHLSL
  47. SubShader
  48. {
  49. Pass
  50. {
  51. Name "Custom Pass 0"
  52. ZWrite On
  53. ZTest Always
  54. Blend SrcAlpha OneMinusSrcAlpha
  55. Cull Off
  56. HLSLPROGRAM
  57. #pragma fragment FullScreenPass
  58. ENDHLSL
  59. }
  60. }
  61. Fallback Off
  62. }

 

这一个材质效果是进行一次横向模糊,将结果缓存在CustomPass的缓冲区,默认是Camera(即直接输出到屏幕 但它还是会做一次混合的 仔细看Shader就能发现 Blend SrcAlpha OneMinusSrcAlpha)

新建一个OutlineV材质球和着色器,着色器代码:

  1. Shader "Hidden/OutlineV"
  2. {
  3. Properties{
  4. _BlurScale("BlurScale", float) = 1
  5. }
  6. HLSLINCLUDE
  7. #pragma vertex Vert
  8. #pragma target 4.5
  9. #pragma only_renderers d3d11 playstation xboxone vulkan metal switch
  10. #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl"
  11. float _BlurScale;
  12. float2 ClampUVs(float2 uv)
  13. {
  14. uv = clamp(uv, 0, _RTHandleScale.xy - _ScreenSize.zw * 2); // clamp UV to 1 pixel to avoid bleeding
  15. return uv;
  16. }
  17. float2 GetSampleUVs(Varyings varyings)
  18. {
  19. float depth = LoadCameraDepth(varyings.positionCS.xy);
  20. PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
  21. return posInput.positionNDC.xy * _RTHandleScale.xy;
  22. }
  23. float4 FullScreenPass(Varyings varyings) : SV_Target
  24. {
  25. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
  26. float depth = LoadCameraDepth(varyings.positionCS.xy);
  27. PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
  28. float4 color = float4(0.0, 0.0, 0.0, 0.0);
  29. //纵向从CustomPass(上一个横向模糊处理后的图片采样,即CustomColor缓冲区) 使用的是uv
  30. // float4 SampleCustomColor(float2 uv);
  31. // float4 LoadCustomColor(uint2 pixelCoords);
  32. //UV获取方式,varyings.positionCS.xy * _ScreenSize.zw为NDC坐标,_RTHandleScale.xy是对NDC坐标进行一个缩放获取uv
  33. float2 uv = ClampUVs(varyings.positionCS.xy * _ScreenSize.zw * _RTHandleScale.xy);
  34. // Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
  35. if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING)
  36. color = SampleCustomColor(uv);
  37. //纵向向模糊
  38. float3 sumColor = 0;
  39. float weight[3] = { 0.4026, 0.2442, 0.0545 };
  40. sumColor = color.rgb * weight[0];
  41. for (int i = 1; i < 3; i++)
  42. {
  43. //注意采用使用的是UV坐标,因此float2(0, _BlurScale * i) * _ScreenSize.zw * _RTHandleScale.xy获取UV坐标增量(偏移值)
  44. sumColor += SampleCustomColor(uv + float2(0, _BlurScale * i) * _ScreenSize.zw * _RTHandleScale.xy).rgb * weight[i];
  45. sumColor += SampleCustomColor(uv + float2(0, _BlurScale * -i) * _ScreenSize.zw * _RTHandleScale.xy).rgb * weight[i];
  46. }
  47. return float4(sumColor, 1);
  48. }
  49. ENDHLSL
  50. SubShader
  51. {
  52. Pass
  53. {
  54. Name "Custom Pass 0"
  55. ZWrite On
  56. ZTest Always
  57. Blend SrcAlpha OneMinusSrcAlpha
  58. Cull Off
  59. HLSLPROGRAM
  60. #pragma fragment FullScreenPass
  61. ENDHLSL
  62. }
  63. }
  64. Fallback Off
  65. }

注意看选中的是Camera,第二次采样的是CustomPass的图片(第一次横向模糊输出的图片)对它进行了一个纵向模糊,然后输出到Camera。

代码很简单,比较难理解的是第一个横向模糊shader是使用

CustomPassSampleCameraColor(posInput.positionNDC.xy, 0) 获取了一个float3,其中采样坐标是NDC坐标。

第二个纵向模糊shader是使用

SampleCustomColor(uv) 获取float4 它是从CustomPass缓存的图片采样的,必须先进行横向模糊输出custom后 才能进行纵向模糊 ,当然你也可以反过来,使用先纵向后横向,但肯定是最后一个进行的模糊要是从Custom来获取上一次的处理结果,而不能再去使用CustomPassSampleCameraColor,因为这个看英文就知道它就是从摄像机缓存获取图片,这个就是当前渲染到的屏幕图而已。

重点内容是:

UV获取方式:varyings.positionCS.xy * _ScreenSize.zw为NDC坐标,_RTHandleScale.xy是对NDC坐标进行一个缩放获取uv

即 uv = varyings.positionCS.xy * _ScreenSize.zw * _RTHandleScale.xy);

uv = clamp(uv, 0, _RTHandleScale.xy - _ScreenSize.zw * 2); // clamp UV to 1 pixel to avoid bleeding

对uv进行clamp处理是将uv约束在1个像素范围以内,这个不太懂了。

其中NDC坐标系是用 varyings.positionCS.xy * _ScreenSize.zw 获取的,当你想做偏移float2(1,0)时,只要将这个float2(1,0)理解成positionCS.xy即可。

positonCS是Homogenous clip spaces(同质剪辑空间)裁剪空间?

_ScreenSize.zw是一个能让裁剪空间缩放回NDC坐标系的缩放系数?

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/101683
推荐阅读
相关标签
  

闽ICP备14008679号