【unity】RenderFeature的应用(生成水平面的网格线)
在URP里RenderFeature是用于后处理效果上的,也还可以实现一些特殊的效果,比如生成网格线。我们可以使用 CommandBuffer来创建地面网格,这样的话可以通过调整 CommandBuffer的参数来控制地面网格的密度。
实现效果
创建流程
- 创建RenderFeature模板
- 编写CommandBuffer生成网格方法
- 增加到 渲染管线资产
创建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) 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.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();
}
内置渲染管线使用 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 100Pass{ ZWrite[_ZWrite]Blend SrcAlpha OneMinusSrcAlphaCGPROGRAM#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}}
}