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

news2024/11/15 11:41:44

【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) 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 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
		}
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/712390.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【NOSQL】redis哨兵模式、集群搭建

目录 一、redis高可用一、Redis主从复制1.1主从复制的作用1.2主从复制流程 二、搭建Rdeis主从复制2.1安装redis2.1.1环境准备2.1.2安装redis2.1.3设置环境变量2.1.4定义systemd服务管理脚本 2.2修改 Redis 配置文件&#xff08;Master节点操作2.3修改 Redis 配置文件&#xff0…

【SpringMVC】| 异常处理器、基于全注解配置SpringMVC

目录 异常处理器 1. 基于配置的异常处理 2. 基于注解的异常处理&#xff08;用类代替xml配置&#xff09; 基于全注解配置SpringMVC 1. 创建初始化类&#xff0c;代替web.xml 2. 创建SpringConfig配置类&#xff0c;代替spring的配置文件 3. 创建WebConfig配置类&#…

哈夫曼树的原理及构造方法

目录 1. 什么是哈夫曼树 2. 为什么有哈夫曼树 3. 哈夫曼树的原理 3.1 哈夫曼树的构造方法 3.2 哈夫曼解码 3.3 几种定义 4. 哈夫曼二叉树的特点 5. 关于哈夫曼树的代码 1. 什么是哈夫曼树 哈夫曼树解决的是编码问题&#xff0c;给定N个权值作为N个叶子结点&#xff0c;构…

Springboot tomcat bean 默认作用域 singleton 情况下模拟线程不安全情况 设置多例方式 prototype

目录 写一个控制层的类 验证方法 ​编辑 分别执行如下请求&#xff0c;先执行等待时间久的 日志结果 结论 配置多例模式 配置文件application.properties 类加注解 配置类方式 写一个控制层的类 package com.example.ctr;import lombok.extern.slf4j.Slf4j; import …

【ISE】PlanAhead report_timing报VIOLATED问题

这里写自定义目录标题 背景ISE PR结果PlanAhead结果使用ISE twx使用PlanAhead综合、实现 问题 分析Timer Settings 结论&#xff1f; 背景 最近调试一个老型号FPGA&#xff0c;时序问题分析&#xff0c;方便以后参考。 ISE PR结果 在下图可以看到All Constraints Met&#x…

iOS iPadOS safari 独立Web应用屏幕旋转的时候 onresize window.innerHeight 数值不对。

iOS iPadOS safari 独立Web应用屏幕旋转的时候 onresize window.innerHeight 数值不对 一、问题描述 我有一个日记应用&#xff0c;是可以作为独立 Web 应用运行的那种&#xff0c;但在旋转屏幕的时候获取到的 window.innerHeight 和 window.innerWidth 就不对了&#xff0c;…

【C#】使用System.Data.SqlClient 进行简单批量操作

在实际项目开发中&#xff0c;可能会在定时任务里进行批量添加的操作&#xff0c;或者需要写一些小工具进行批量添加测试。 此篇文章就是使用System.Data.SqlClient 进行简单批量操作。 目录 1、批量插入数据1.1、示例代码1.2、列映射1.3、是否需要映射列 2、批量更新数据3、链…

ZigBee组网-基于协议栈的UART实验(实现收发)(保姆级)

目录 基于协议栈的UART实验 前言 协议栈中的TI自带UART的使用实验 UART配置基本步骤 串口初始化 串口发送 串口接收回显 实验效果 拓展 移植我们自己UART串口 移植配置过程 实验效果 基于协议栈的UART实验 前言 与之前的Zigbee裸机实验不同&#xff0c;我们既可以…

神奇的MATLAB解密工具,让你轻松解密.p文件!

大家都知道&#xff0c;MATLAB是一款功能强大的数学软件&#xff0c;但是在进行代码保护和共享方面&#xff0c;却存在一些困难。这时候&#xff0c;一款优秀的MATLAB解密工具就显得尤为重要。它可以帮助我们解决诸多问题&#xff0c;比如.p文件解密、p文件转m代码等。接下来&a…

mallocstacklogging和MallocStackLoggingNoCompact引起的app文稿数据快速增加

最近由于定位一个iOS16系统适配引起的闪退设置了mallocstacklogging和MallocStackLoggingNoCompact。 配置如下&#xff1a; 在上线前测试&#xff0c;结果发现手机存储空间不足。删除了手机的很多图片后&#xff0c;测试不到两分钟&#xff0c;手机存储空间又不足了。查看app…

Flink运行原理

Apache Flink是什么&#xff1f;对于这个问题&#xff0c;Apache软件基金会官方给出了定义&#xff1a;Flink是一种框架和分布式处理引擎&#xff0c;主要用于对无界和有界数据流进行有状态计算。 本文将从以下几个方面来了解flink运行原理&#xff1a; 【Flink运行时四大组件…

骨传导耳机可以长期佩戴吗,几款佩戴舒适的骨传导耳机清单

骨传导耳机是通过耳朵传声方式&#xff0c;提高了听神经的使用频率&#xff0c;对听觉系统所产生刺激会随之下降。目前骨传导耳机主要应用于运动和娱乐两大领域&#xff0c;尤其是在运动场景中骨传导耳机能够避免传统耳机因佩戴入耳式耳机造成的听力下降问题&#xff0c;更能增…

Python批量将doc转成docx并读取docx的内容

有时候我们需要将doc的文件转成docx的格式&#xff0c;但是如果直接修改文件名后缀的话有时候会没有效果&#xff0c;今天我们利用python批量将doc后缀的word文档转成docx的格式。 也找了很多方法&#xff0c;最终还是找到了就是利用win32com去解决这个问题 很多人在执行这一…

【MySQL】不就是事务

前言 嗨咯&#xff0c;小伙伴们大家好呀&#xff0c;我已经一个星期没有更新了&#xff0c;实在抱歉&#xff01;本期我们要学习MySQL初阶中的最后一课&#xff0c;MySQL数据库中的事务也算是近几年面试必考的问题&#xff0c;所以我们一定要认真学习。 目录 前言 目录 一、事…

学会用智慧轻松的方式过生活

曾经&#xff0c;有位远在黑龙江的女性福主告诉峰民&#xff0c;她说她活不久了。 峰民很是惊讶&#xff0c;不可能吧&#xff0c;你才39岁啊&#xff0c; 她说&#xff1a;我查出了子宫有瘤&#xff0c;峰民听后就说&#xff0c;没事&#xff0c;放心&#xff0c;肯定是良性。…

Python3,处理Excel文件IO流的方法那么多,或许只有Pandas算得上靠谱。

Pandas处理Excel文件IO流的方法 1、引言2、代码实例2.1 什么是文件IO流2.1.1定义2.1.2 字节流、字符流 2.2 常见的Excel文件IO流处理方法2.3 Pandas处理Excel文件IO流2.3.1 直接读取处理2.3.2 转换io流进行处理 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c; 求助。 小…

深度学习技巧应用22-构建万能数据生成类的技巧,适用于CNN,RNN,GNN模型的调试与训练贯通

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下深度学习技巧应用22-构建万能数据生成类的技巧&#xff0c;适用于CNN,RNN,GNN模型的调试与训练贯通。本文将实现了一个万能数据生成类的编写&#xff0c;并使用PyTorch框架训练CNN、RNN和GNN模型。 目录&#xff1…

摄像机控制——旁轴摇移

通常摄像机进行摇移控制的时候&#xff0c;都是以摄像机正前方中心位置作为注视点进行环绕控制的&#xff0c;如果在注释点位置有物体&#xff0c;那么感受上是围绕着该物体进行观察。 但是最近公司的策划要求摇移时候的围绕点是鼠标点击的位置&#xff0c;而不是摄像机的正中心…

零基础网络安全学习路线,真的很全,建议收藏!!!

很多小伙伴在网上搜索网络安全时&#xff0c;会出来网络安全工程师这样一个职位&#xff0c;它的范围很广&#xff0c;只要是与网络安全挂钩的技术人员都算网络安全工程师&#xff0c;一些小伙伴就有疑问了&#xff0c;网络安全现在真的很火吗&#xff1f; 那么今天博主就带大…

从0实现基于Linux socket聊天室-多线程服务器模型(一)

前言Socket在实际系统程序开发当中&#xff0c;应用非常广泛&#xff0c;也非常重要。实际应用中服务器经常需要支持多个客户端连接&#xff0c;实现高并发服务器模型显得尤为重要。高并发服务器从简单的循环服务器模型处理少量网络并发请求&#xff0c;演进到解决C10K&#xf…