当前位置:   article > 正文

初识Unity SRP_unity shader srp是什么

unity shader srp是什么

Unity SRP 即 Unity Scriptable Rendering Pipeline(可编程渲染管线),是Unity 2018的新功能,使开发者可以通过脚本按需构建自己的渲染过程。在学习和参考:

吉祥的游戏编程笔记

中关于Unity SRP的相关内容后,这里做一个简单的学习记录,如有错误之处,希望可以多多交流。
SRP中的内容可以用一张图说明: SRP的创建过程分为3个部分:

  • Custom Render Pipeline
  • Custom Render Pipeline Asset
  • Shader

Custom Render Pipeline

该部分是自定义渲染管线的起点,也是核心部分,继承自RenderPipeline类。在该类中的Render()方法中,定义自己的渲染流程中的规则及进行参数设置。一般来说,渲染的过程是将摄像机视野中3D或2D的场景对象进过一系列的处理最后转换成一张2D的图片输出到屏幕上。因此在Render()方法中,处理起点是从编辑场景里的每一个输出相机开始,经过如下过程:

  • 设置渲染目标
  • 绘制天空盒
  • 执行裁剪过程
  • 执行过滤过程
  • 绘制场景准备
  • 执行管线

在这一系列的过程中,需要将相关的指令和设置提交,通过 CommandBuffer和ScriptableRenderContext对象实现。 CommandBuffer对象作为指令缓存集,记录部分指令然后集中提交。ScriptableRenderContext对象可以理解成渲染过程中的一个管理器,CommandBuffer对象的指令提交需要通过ScriptableRenderContext对象完成,同时ScriptableRenderContext对象还可以管理如天空球的绘制、下达执行管线渲染等操作。
Custom Render Pipeline 完整代码:

  1. using UnityEngine;
  2. using UnityEngine.Experimental.Rendering;
  3. using UnityEngine.Rendering;
  4. namespace Kata03 {
  5. public class CustomRenderPipeline : RenderPipeline
  6. {
  7. CommandBuffer _cb;
  8. //该函数在管线销毁时调用
  9. public override void Dispose()
  10. {
  11. base.Dispose();
  12. if (_cb != null) {
  13. _cb.Clear();
  14. _cb = null;
  15. }
  16. }
  17. //该函数在管线渲染时调用
  18. public override void Render(ScriptableRenderContext renderContext, Camera[] cameras)
  19. {
  20. base.Render(renderContext, cameras);
  21. if (_cb == null) {
  22. _cb = new CommandBuffer();
  23. }
  24. //设置Shader中要使用的光源变量名
  25. var _LightDir = Shader.PropertyToID("_LightDir");
  26. var _LightColor = Shader.PropertyToID("_LightColor");
  27. var _CameraPos = Shader.PropertyToID("_CameraPos");
  28. //对于每个相机执行的操作
  29. foreach (var camera in cameras)
  30. {
  31. //设置渲染上下文相机属性
  32. renderContext.SetupCameraProperties(camera);
  33. _cb.name = "Setup";
  34. //显式设置渲染目标为相机BackBuffer(如果相机没有指定渲染纹理,则直接绘制到屏幕)
  35. _cb.SetRenderTarget(BuiltinRenderTextureType.CameraTarget);
  36. //设置渲染目标颜色为相机背景色
  37. _cb.ClearRenderTarget(true, true, camera.backgroundColor);
  38. //设置相机的着色器全局变量
  39. Vector4 CameraPosition = new Vector4(camera.transform.localPosition.x, camera.transform.localPosition.y, camera.transform.localPosition.z, 1.0f);
  40. _cb.SetGlobalVector(_CameraPos, camera.transform.localToWorldMatrix * CameraPosition);
  41. renderContext.ExecuteCommandBuffer(_cb);
  42. _cb.Clear();
  43. //天空盒绘制
  44. renderContext.DrawSkybox(camera);
  45. //执行裁剪
  46. var culled = new CullResults();
  47. CullResults.Cull(camera, renderContext, out culled);
  48. /*
  49. 裁剪结果包括:
  50. 可见的物体列表:visibleRenderers
  51. 可见灯光列表:visibleLights
  52. 可见反射探针(CubeMap):visibleReflectionProbes
  53. 裁剪结果并未排序
  54. */
  55. //获取所有灯光
  56. var lights = culled.visibleLights;
  57. _cb.name = "RenderLights";
  58. foreach (var light in lights)
  59. {
  60. //挑选出平行光处理
  61. if (light.lightType != LightType.Directional) continue;
  62. //获取光源方向
  63. Vector4 pos = light.localToWorld.GetColumn(0);
  64. Vector4 lightDir = new Vector4(pos.x,pos.y,pos.z,0);
  65. //获取光源颜色
  66. Color lightColor = light.finalColor;
  67. //构建shader常量缓存
  68. _cb.SetGlobalVector(_LightDir,lightDir);
  69. _cb.SetGlobalColor(_LightColor,lightColor);
  70. renderContext.ExecuteCommandBuffer(_cb);
  71. _cb.Clear();
  72. var rs = new FilterRenderersSettings(true);
  73. //只渲染固体范围
  74. rs.renderQueueRange = RenderQueueRange.opaque;
  75. //包括所有层
  76. rs.layerMask = ~0;
  77. //渲染设置,使用Shader中LightMode为"BaseLit"的Pass
  78. var ds = new DrawRendererSettings(camera,new ShaderPassName("BaseLit"));
  79. //物体绘制
  80. renderContext.DrawRenderers(culled.visibleRenderers,ref ds,rs);
  81. break;
  82. }
  83. //开始执行管线
  84. renderContext.Submit();
  85. }
  86. }
  87. }
  88. }

Custom Render Pipeline Asset

Custom Render Pipeline Asset 继承自 Render Pipeline Asset,用来在项目中生成自定义渲染管线资源,主要实现 IRenderPipelineAsset接口方法, InternalCreatePipeline(),生成自定义的 Custom RenderPipeline 对象,完整代码:

  1. using UnityEngine.Experimental.Rendering;
  2. #if UNITY_EDITOR
  3. using UnityEditor;
  4. using UnityEditor.ProjectWindowCallback;
  5. #endif
  6. namespace Kata03 {
  7. public class CustomRenderPipelineAsset : RenderPipelineAsset
  8. {
  9. #if UNITY_EDITOR
  10. [MenuItem("Assets/Create/Render Pipeline/Kata03/Pipeline Asset")]
  11. static void CreateKata03Pipeline() {
  12. ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0,CreateInstance<CreateKata03PipelineAsset>(),"Kata03 Pipeline.asset",null,null);
  13. }
  14. class CreateKata03PipelineAsset : EndNameEditAction
  15. {
  16. public override void Action(int instanceId, string pathName, string resourceFile)
  17. {
  18. var instance = CreateInstance<CustomRenderPipelineAsset>();
  19. AssetDatabase.CreateAsset(instance,pathName);
  20. }
  21. }
  22. #endif
  23. protected override IRenderPipeline InternalCreatePipeline()
  24. {
  25. return new CustomRenderPipeline();
  26. }
  27. }
  28. }

有了 Custom Render Pipeline Asset 后,在Projects中通过 Create->RdnerPipeline->Kata03->Pipeline 即可创建对应的自定义渲染管线资源,然后替换原有的管线,在Edit->Project->Settings->Graphics中的Scriptable Render PipelineLine Settings中完成替换。

Shader

Shader是配合当前的自定义管线,完成场景内的物体着色,这和之前使用Unity内置管线没有区别。只是这里有一点需要注意的是:
在CustomRenderPipeline的渲染设置中,

var ds = new DrawRendererSettings(camera,new ShaderPassName("BaseLit"));

这里在构建ShaderPassName对象时,传递的参数为使用的Shader的Pass中"LightMode"对应的名称,因为在自定义渲染管线中,场景内物体光照着色的区分是通过Shader内的Pass里的"LightMode"进行的。包含光照计算的Shader代码:

  1. Shader "Custom/BaseDirLit"
  2. {
  3. Properties
  4. {
  5. _Color("Tint", Color) = (0.5,0.5,0.5,1)
  6. _DiffuseFactor("Diffuse Factor", Range(0,1)) = 1
  7. _SpecularColor("Specular Color",Color)=(1,1,1,1)
  8. _SpecularFactor("Specular Factor", Range(0,1)) = 1
  9. _SpecularPower("Specular Power",Float) = 100
  10. }
  11. HLSLINCLUDE
  12. #include "UnityCG.cginc"
  13. #define PI 3.14159265359
  14. uniform float4 _LightDir;
  15. uniform float4 _LightColor;
  16. uniform float4 _CameraPos;
  17. uniform float4 _Color;
  18. uniform float _DiffuseFactor;
  19. uniform float _SpecularFactor;
  20. uniform float _SpecularColor;
  21. uniform float _SpecularPower;
  22. struct a2v
  23. {
  24. float4 vertex : POSITION;
  25. float4 normal : NORMAL;
  26. };
  27. struct v2f
  28. {
  29. float4 pos : SV_POSITION;
  30. float4 normalWorld : TEXCOORD1;
  31. float4 worldPos : TEXCOORD2;
  32. };
  33. v2f vert(a2v v)
  34. {
  35. v2f o;
  36. UNITY_INITIALIZE_OUTPUT(v2f,o);
  37. o.pos = UnityObjectToClipPos(v.vertex);
  38. o.normalWorld = float4(normalize(mul(normalize(v.normal.xyz), (float3x3)unity_WorldToObject)),v.normal.w);
  39. o.worldPos = mul(unity_ObjectToWorld,v.vertex);
  40. return o;
  41. }
  42. half4 frag(v2f i) : SV_Target
  43. {
  44. fixed4 diffuse=_DiffuseFactor*max(0.0,dot(_LightDir.xyz,normalize(i.normalWorld.xyz)))*_Color*_LightColor;
  45. fixed3 viewDir=normalize(_CameraPos.xyz-i.worldPos.xyz);
  46. fixed3 halfDir=normalize(_LightDir.xyz+viewDir);
  47. fixed4 specular= _LightColor*_SpecularFactor*pow(max(0,dot(normalize(i.normalWorld.xyz),halfDir)),_SpecularPower)*max(0,saturate(dot(normalize(i.normalWorld.xyz),_LightDir.xyz)))*(_SpecularPower+8)/(8+PI);
  48. return diffuse+specular;
  49. }
  50. ENDHLSL
  51. SubShader
  52. {
  53. Tags{ "Queue" = "Geometry" }
  54. LOD 100
  55. Pass
  56. {
  57. Tags {"LightMode" = "BaseLit"}
  58. HLSLPROGRAM
  59. #pragma vertex vert
  60. #pragma fragment frag
  61. ENDHLSL
  62. }
  63. }
  64. }

在场景中使用该Shader的材质,得到的对应效果:

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

闽ICP备14008679号