Unity SRP 可编程渲染管线的基本用法

可编程渲染管线使用教程

SRP 可以处理Canvas为Screen Space - Overlay的渲染

安装插件

首先进入package manager,下载Core RP Lib组件

创建渲染管线

编写渲染管线逻辑脚本

新建脚本取名为MPipeLine,该脚本用于实现渲染管线的处理逻辑

csharp 复制代码
using UnityEngine;
using UnityEngine.Rendering;

public class MPipeLine : RenderPipeline
{
    public MPipeLine() { }

    protected override void Render(ScriptableRenderContext context, Camera[] cameras)
    {
        // 创建渲染指令,默认填充白色
        var cmd = new CommandBuffer();
        cmd.ClearRenderTarget(true, true, Color.white);
        context.ExecuteCommandBuffer(cmd);
        cmd.Release();

        // 提交渲染指令
        context.Submit();
    }
}

编写渲染管线与编辑器关联

创建脚本MPipelineAsset,用于与unity编辑器建立关联,允许将工程与自定义渲染管线进行绑定

csharp 复制代码
using UnityEngine;
using UnityEngine.Rendering;

[CreateAssetMenu(menuName = "Rendering/MPipelineAsset")]
public class MPipelineAsset : RenderPipelineAsset
{
    protected override RenderPipeline CreatePipeline()
    {
    	// 渲染逻辑脚本
        return new MPipeLine();
    }
}

创建并配置PipeLine Asset

首先创建Asset文件

点击Edit > projectsettings > graphics,设置asset为我们刚才新建的那个管线资源

编辑渲染管线逻辑

渲染逻辑有两种写法,一种是直接创建指令

csharp 复制代码
    //var cmd = new CommandBuffer() { name = "clear" };
    //cmd.ClearRenderTarget(true, true, Color.white);
    //context.ExecuteCommandBuffer(cmd);
    //cmd.Release();
    //context.Submit();

另一种是调用渲染api来实现,所有的逻辑要包在Begin、end之间

csharp 复制代码
    RenderPipeline.BeginFrameRendering(context, cameras);
    // 要渲染的相机
    Camera camera = cameras[0];
    // 相机渲染   不透明
    RenderCamera(context, camera, "shader1", SortingCriteria.CommonOpaque, RenderQueueRange.opaque);
    RenderCamera(context, camera, "shader2", SortingCriteria.CommonTransparent, RenderQueueRange.transparent);

    // 结束帧渲染你
    RenderPipeline.EndFrameRendering(context, cameras);

我们这里使用后者来分别创建透明、不透明、及天空盒的渲染逻辑

csharp 复制代码
  protected override void Render(ScriptableRenderContext context, Camera[] cameras)
  {
      // 开始帧渲染
      RenderPipeline.BeginFrameRendering(context, cameras);
      // 要渲染的相机
      Camera camera = cameras[0];
      // 相机渲染   不透明, shader1是自建shader,代码在后面
      RenderCamera(context, camera, "shader1", SortingCriteria.CommonOpaque, RenderQueueRange.opaque);
      // 相机渲染   不透明, shader2是自建shader,代码在后面
      RenderCamera(context, camera, "shader2", SortingCriteria.CommonTransparent, RenderQueueRange.transparent);

      // 结束帧渲染
      RenderPipeline.EndFrameRendering(context, cameras);
  }
  
  private void RenderCamera(ScriptableRenderContext context, Camera camera, string TagId, SortingCriteria criteria, RenderQueueRange queue)
  {
      // 开始渲染摄像机
      RenderPipeline.BeginCameraRendering(context, camera);

      // Camera 区域剔除
      ScriptableCullingParameters cullingParameters = new ScriptableCullingParameters();
      cullingParameters.cullingOptions |= CullingOptions.OcclusionCull;
      // 剔除除了default layer之外的layer
      cullingParameters.cullingMask = 1 << 0;
      camera.TryGetCullingParameters(out cullingParameters);
      var cullingResults = context.Cull(ref cullingParameters);

      // 更新当前摄像机内置着色器变量值
      context.SetupCameraProperties(camera);

      // DrawingSettings用来描述可见物体的排序方式,以及绘制使用的Shader Pass
      ShaderTagId shaderTagId = new ShaderTagId(TagId);
      var sortingSettings = new SortingSettings(camera) {
          criteria = criteria 
      };
      DrawingSettings drawingSettings = new DrawingSettings(
          shaderTagId, 
          sortingSettings
      );

     // 过滤  FilteringSettings用来描述渲染时如何过滤可见物体
      FilteringSettings filteringSettings = new FilteringSettings(queue);

      // 绘制图形
      context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);

      // 绘制天空盒
      if (camera.clearFlags == CameraClearFlags.Skybox && RenderSettings.skybox != null && queue != RenderQueueRange.transparent)
      {
          context.DrawSkybox(camera);
      }

      // 提交渲染按 
      context.Submit();

      // 结束渲染摄像机
      RenderPipeline.EndCameraRendering(context, camera);
  }

创建着色器

分别创建shader1.shader, shader2.shader两个着色器资源,并将下列代码填入

shader1:

hlsl 复制代码
Shader "Custom/mShader1"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
     Blend One OneMinusSrcAlpha
        Pass
        {
            Tags { "LightMode"="shader1" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

shader2:

shader 复制代码
Shader "Custom/mShader2"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "#A84242" {}
        _MainColor("color", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags{
            "Queue" = "Transparent"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
        }
        Cull Off
        //Lighting On 
        //ZWrite On
        Blend One OneMinusSrcAlpha
        Pass
        {
            Tags { "LightMode"="shader2" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _MainColor;
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv) * _MainColor;
                // apply fog
                //UNITY_APPLY_FOG(i.fogCoord, col);
                col.a = _MainColor.a;
                return col;
            }
            ENDCG
        }
    }
}

测试效果

然后创建材质mat1.materil、mat2.materil。 mat1关联shader1,mat2关联shader2,将mat2的color透明度调到100

在场景中创建cube1和cube2两个方形物体,这时我们是什么都看不到的。

拖动cube2,一部分挡在cube1前面,并将mat1赋给cube1,mat2赋给cube2。此时我们就能看到自定义渲染管线生效了

相关推荐
谷宇.7 小时前
【Unity3D实例-功能-拔枪】角色拔枪(三)IK的使用-紧握武器
游戏·unity·c#·unity3d·游戏开发·游戏编程·steam
SmalBox16 小时前
【渲染流水线】[逐片元阶段]-[模版测试]以UnityURP为例
unity·渲染
小蜗 strong19 小时前
unity中实现机械臂自主运动
unity·游戏引擎
★YUI★1 天前
学习游戏制作记录(制作系统与物品掉落系统)8.16
学习·游戏·ui·unity·c#
SmalBox2 天前
【渲染流水线】[逐片元阶段]-[透明度测试]以UnityURP为例
unity·渲染
三只坚果2 天前
blender制作动画导入unity两种方式
unity·游戏引擎·blender
benben0442 天前
《Unity Shader入门精要》学习笔记二
unity·unity shader
YF云飞2 天前
Unity音频管理:打造沉浸式游戏音效
游戏·unity·游戏引擎·游戏程序·个人开发
SmalBox2 天前
【渲染流水线】[逐片元阶段]-[裁剪测试]以UnityURP为例
unity·渲染
与火星的孩子对话3 天前
Unity高级开发:反射原理深入解析与实践指南 C#
java·unity·c#·游戏引擎·lucene·反射