【unity】RenderFeature的应用(生成水平面的网格线)

【unity】RenderFeature的应用(生成水平面的网格线)

在URP里RenderFeature是用于后处理效果上的,也还可以实现一些特殊的效果,比如生成网格线。我们可以使用 CommandBuffer来创建地面网格,这样的话可以通过调整 CommandBuffer的参数来控制地面网格的密度。

实现效果

创建流程

  1. 创建RenderFeature模板
  2. 编写CommandBuffer生成网格方法
  3. 增加到 渲染管线资产

创建RenderFeature模板

  • 在Project面板Create→Rendering→URP Renderer Feature,默认命名为CustomRenderPassFeature

简介

URP Renderer Feature模板继承ScriptableRendererFeature

ScriptableRendererFeature由两个类 CustomRenderPassFeature 与 CustomRenderPass 组成,CustomRenderPass继承ScriptableRenderPass

ScriptableRendererFeature

Create:是用来初始化这个 Feature 的资源

AddRenderPasses:在 Renderer 中插入一个或多个 ScriptableRenderPass

ScriptableRenderPass

Configure :在执行渲染过程之前,Renderer 将调用此方法

Execute:是这个类的核心方法,定义我们的执行规则 ,实现渲染逻辑

FrameCleanup:可用于释放通过此过程创建的分配资源

编写CommandBuffer生成网格方法

在创建的RenderFeature模板中编写脚本如下:

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class CustomRenderPassFeature : ScriptableRendererFeature
{
  
    public float lineCount; 
  
    class CustomRenderPass : ScriptableRenderPass
    {
        public float lineCount;
        public   bool isRender = false;
        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
             if (!Application.isPlaying|| !isRender) return;
            ProfilingSampler mProfilingSampler = new ProfilingSampler("Test1");
            CommandBuffer cmd = CommandBufferPool.Get("Test1 Cmd");
            Material cmdMat1 = new Material(Shader.Find("Models/LineShader"));
            using (new ProfilingScope(cmd, mProfilingSampler))
            {
                Mesh meshRenderer = CreateGridMesh(Color.green, lineCount);
                cmd.DrawMesh(meshRenderer, Matrix4x4.identity, cmdMat1);
                context.ExecuteCommandBuffer(cmd);
                CommandBufferPool.Release(cmd);
            }
        }

      /// <summary>
      /// 创建网格
      /// </summary>
      /// <param name="color"></param>
      /// <param name="spacing"></param>
      /// <param name="linesCount"></param>
      /// <returns></returns>
        public Mesh CreateGridMesh(Color color, float spacing, int linesCount = 150)
        {
            int count = linesCount / 2;
            Mesh mesh = new Mesh();
            mesh.name = "Grid " + spacing;
            int index = 0;
            int[] indices = new int[count * 8];
            Vector3[] vertices = new Vector3[count * 8];
            Color[] colors = new Color[count * 8];
            for (int i = -count; i < count; ++i)
            {
                vertices[index] = new Vector3(i * spacing, 0, -count * spacing);
                vertices[index + 1] = new Vector3(i * spacing, 0, count * spacing);

                vertices[index + 2] = new Vector3(-count * spacing, 0, i * spacing);
                vertices[index + 3] = new Vector3(count * spacing, 0, i * spacing);

                indices[index] = index;
                indices[index + 1] = index + 1;
                indices[index + 2] = index + 2;
                indices[index + 3] = index + 3;
                colors[index] = colors[index + 1] = colors[index + 2] = colors[index + 3] = color;
                index += 4;
            }
            Debug.Log(vertices.Length);
            mesh.vertices = vertices;
            mesh.SetIndices(indices, MeshTopology.Lines, 0);
            return mesh;
        }
    }
    CustomRenderPass m_ScriptablePass;

    /// <inheritdoc/>
    public override void Create()
    {
        m_ScriptablePass = new CustomRenderPass();
        m_ScriptablePass.lineCount = lineCount;
        m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
    }
    /// <summary>
    /// 用于修改参数
    /// </summary>
    public void SetParam()
    {
        m_ScriptablePass.isRender = true;
        m_ScriptablePass.lineCount = lineCount;
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(m_ScriptablePass);
    }
}

增加到渲染管线资产(RenderPipelineAsset)

  • 找到URP Asset(位置: Edit→ProjectSetting→Quality→Rendering→RenderPipelineAsset)
  • 找到URP Universal Renderer(位置:URP Asset→Rendering→RendererList)
  • 增加Renderer Feature,点击URP Universal Renderer的Add Renderer Feature添加之前创建的Renderer Feature模板

补充

RenderFeature模板自定义参数调整方法

方法一:

    CustomRenderPassFeature custom=renderData.rendererFeatures.OfType<CustomRenderPassFeature>().FirstOrDefault();
     custom.lineCount =200;
     custom.SetParam();

方法二:

    [SerializeField]    
    UniversalRendererData renderData;
    List<ScriptableRendererFeature> rendererFeatures;
    Dictionary<string, ScriptableRendererFeature> innerFeatures = new Dictionary<string, ScriptableRendererFeature>();
    CustomRenderPassFeature custom;

     void Start()
    {
        rendererFeatures = renderData.rendererFeatures;
        for (int i = 0; i < rendererFeatures.Count; i++)
        {
            var feature = rendererFeatures[i];
            innerFeatures[feature.name] = feature;
        }
        ScriptableRendererFeature rendererFeature;
        innerFeatures.TryGetValue("CustomRenderPassFeature", out rendererFeature);
         custom = rendererFeature as CustomRenderPassFeature;
    }
void SetParam()
{
            custom.lineCount = 200;
            custom.SetParam();    
}
void Clear()
    {
        custom.Clear();
    }
内置渲染管线使用 CommandBuffer来创建地面网格
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

public class CommandBufferTest : MonoBehaviour
{
    CommandBuffer cmdBuffer;
    public Material cmdMat1;
    public Camera mainCamera;
    public float m_alpha = 1.0f;
    bool m_zTest = false;
    Mesh m_grid0Mesh;
    private void Start()
    {
        cmdBuffer = new CommandBuffer() { name = "CameraCmdBuffer" };
        mainCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmdBuffer);
        m_zTest = true;
        DrawMesh();
    }
    //关机调用
    void OnDestroy()
    {
        Cleanup();
    }
    //卸载调用
    void OnDisable()
    {
        Cleanup();
    }
    //载入调用
    void OnEnable()
    {
        if (m_zTest)
        
        DrawMesh();
    }
    public void DrawMesh()
    {
        cmdBuffer.Clear();
        m_grid0Mesh = CreateGridMesh(Color.green, 10);
        cmdBuffer.DrawMesh(m_grid0Mesh, Matrix4x4.identity, cmdMat1);
    }

    public Mesh CreateGridMesh(Color color, float spacing, int linesCount = 150)
    {
        int count = linesCount / 2;

        Mesh mesh = new Mesh();
        mesh.name = "Grid " + spacing;

        int index = 0;
        int[] indices = new int[count * 8];
        Vector3[] vertices = new Vector3[count * 8];
        Color[] colors = new Color[count * 8];

        for (int i = -count; i < count; ++i)
        {
            vertices[index] = new Vector3(i * spacing, 0, -count * spacing);
            vertices[index + 1] = new Vector3(i * spacing, 0, count * spacing);

            vertices[index + 2] = new Vector3(-count * spacing, 0, i * spacing);
            vertices[index + 3] = new Vector3(count * spacing, 0, i * spacing);

            indices[index] = index;
            indices[index + 1] = index + 1;
            indices[index + 2] = index + 2;
            indices[index + 3] = index + 3;

            colors[index] = colors[index + 1] = colors[index + 2] = colors[index + 3] = color;

            index += 4;
        }
        mesh.vertices = vertices;
        mesh.SetIndices(indices, MeshTopology.Lines, 0);
        return mesh;
    }
    private void Cleanup()
    {
        if (m_grid0Mesh != null)
        {
            Destroy(m_grid0Mesh);
        }
    }
}

LineShader
Shader "Models/LineShader"
{
	Properties
	{
		_Color("Color", Color) = (1, 1, 1, 1) 
		[Enum(Off,0,On,1)]_ZWrite("ZWrite", Float) = 1.0
	}

	SubShader
	{
		Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
		LOD 100
	
		Pass
		{ 
			ZWrite[_ZWrite]
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			// make fog work
			#pragma multi_compile_fog

			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
			};

			struct v2f
			{
				float4 vertex : SV_POSITION;
			};

			fixed4 _Color;

			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				return _Color;
			}
			ENDCG
		}
	}
}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小生云木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值