百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Unity | GrabPass&CommandBuffer&OnRenderImage基础

bigegpt 2024-08-20 10:56 2 浏览

1GrabPass

GrabPass来实现半透材质折射、热空气扭曲等效果。但是性能堪忧,特别是受限于移动端硬件,每次抓屏得到的数据要从GPU拷贝回CPU进行计算,这个数据传输过程是非常耗时的,GrabPass获取到的图像分辨率和显示屏是一致的,这意味着在高分辨率的设备上,这个过程极易造成带宽阻塞。而且GrabPass最耗费性能,OnRenderImage次之,RenderTexture最省。但是抛开剂量谈效果都是耍流氓。RenderTexture需要两个摄像机,DrawCall会翻倍,所以在复杂的场景中,OnRenderImage是最合适做抓屏的。

这里要说一下的是:URP管线并不支持GrabPass,虽然官方提到可以用OpaqueTexture代替功能,顾名思义,OpaqueTexture是在不透明物体渲染之后截取的一张RT,其中不包含半透明物体。如果想要完全和GrabPass一致,可能是不太容易做到的,Unity自带的GrabPass,能在此物体DrawCall的前一次DrawCallBlit一张图片,而我们是无法打开一个渲染队列的,例如半透明物体整体在一个队列中,我们无法在其中插一个Blit

2GrabPass用法

SubShader {
        Pass {
        ......
        }
    GrabPass {
          "_GrabTexture"
        }
        sampler2D _GrabTexture
    Pass {
        ......
    }
}

简单的 GrabPass { } 可将当前屏幕内容抓取到某个纹理中。在随后的通道中可通过 _GrabTexture 名称访问该纹理。注意:这种抓取通道的形式将为使用它的每个对象执行耗时的屏幕抓取操作。

GrabPass { "TextureName" } 可将当前屏幕内容抓取到纹理中,但仅为使用给定纹理名称的第一个对象在每一帧执行一次该操作。在后续通道中可通过给定纹理名称访问该纹理。场景中有多个对象在使用 GrabPass 时,这种方法更高效。

3OnRenderImage

unity shader中的pass是会顺序执行的,但是由于在图像处理中我们常常需要使用一个pass的处理结果作为另一个pass的输入,这个时候就需要用到OnRenderImage()函数了。

函数解释:MonoBehaviour.OnRenderImage(RenderTexture source,RenderTexture destination) 该函数在所有的渲染完成后由monobehavior自动调用。

官方解释:该函数允许我们使用着色器滤波操作来修改最终的图像,输入原图像source,输出的图像放在desitination里。所以,该脚本必须挂载在有相机组件的游戏对象上,在该相机渲染完成后调用OnRenderImage()函数。这里要说一下的是OnRenderImage Scriptable Render Pipeline 并不支持。要在通用渲染管线 (URP) 中创建自定义全屏效果,你需要用ScriptableRenderPass API。如果要在高清渲染管线 (HDRP) 中创建自定义全屏效果,就用Fullscreen Custom Pass的API。

代码示例:

using UnityEngine;


public class ExampleClass : MonoBehaviour
{
    // 用于处理图像的材质
    public Material mat;


    void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        // 从源 RenderTexture 读取像素,应用材质,将更新的结果复制到目标 RenderTexture
        Graphics.Blit(src, dest, mat);
        mat.SetTexture("_MainTex", source);
    }
}


4CommandBuffer

CommandBufferOnRenderImage看起来极为类似,不过OnRenderImage是在渲染结束后执行,而Command Buffer可以插进渲染的任何一步:

Graphics.Blit(RenderTexture src,RenderTexture dest,Material mat=null);//OnRenderImage
CommandBuffer CB=new CommandBuffer();
CB.Blit(RenderTargetIdentifier source,RenderTargetIdentifier dest,Material mat=null);//Command Buffer

如下图,我们可以根据参数指定CommandBuffer在绿色的点上添加执行命令。


好的,让我们现在来实现一个最简单的CommandBuffer。

新建一个Cube ,新建一个Shader,并且将Shader的颜色输出改为绿色。

新建脚本TestCommandBuffer.cs,挂到Cube,脚本上挂新建的Shader

using UnityEngine;
using UnityEngine.Rendering;


[ExecuteInEditMode]
public class TestCommandBuffer : MonoBehaviour
{
    public Shader shader;
    private void OnEnable()
    {
        CommandBuffer buf = new CommandBuffer();
        //设置自己的渲染。
        buf.DrawRenderer(GetComponent<Renderer>(), new Material(shader));
        //不透明物体渲染完后执行
        Camera.main.AddCommandBuffer(CameraEvent.AfterForwardOpaque, buf);
    }
}

同是一个Cube,Game中的为绿色,而Scene中的依旧。打开FrameDebug看一下,发现Cube被绘制了两次。额外多出的一次红色框框那个就是CommandBuffer的渲染。能看得出,CommandBuffer作用就是在相机渲染的某个阶段,再另外执行自己的额外渲染,至于渲染的结果就看我们怎么用了。

如果我们需要做一些需要抓屏幕的操作,如泡泡,高斯模糊玻璃面板这些是会被需要到的。具体用哪种方法,需要参考当前项目选择最优解。

相关推荐

悠悠万事,吃饭为大(悠悠万事吃饭为大,什么意思)

新媒体编辑:杜岷赵蕾初审:程秀娟审核:汤小俊审签:周星...

高铁扒门事件升级版!婚宴上‘冲喜’老人团:我们抢的是社会资源

凌晨两点改方案时,突然收到婚庆团队发来的视频——胶东某酒店宴会厅,三个穿大红棉袄的中年妇女跟敢死队似的往前冲,眼瞅着就要扑到新娘的高额钻石项链上。要不是门口小伙及时阻拦,这婚礼造型团队熬了三个月的方案...

微服务架构实战:商家管理后台与sso设计,SSO客户端设计

SSO客户端设计下面通过模块merchant-security对SSO客户端安全认证部分的实现进行封装,以便各个接入SSO的客户端应用进行引用。安全认证的项目管理配置SSO客户端安全认证的项目管理使...

还在为 Spring Boot 配置类加载机制困惑?一文为你彻底解惑

在当今微服务架构盛行、项目复杂度不断攀升的开发环境下,SpringBoot作为Java后端开发的主流框架,无疑是我们手中的得力武器。然而,当我们在享受其自动配置带来的便捷时,是否曾被配置类加载...

Seata源码—6.Seata AT模式的数据源代理二

大纲1.Seata的Resource资源接口源码2.Seata数据源连接池代理的实现源码3.Client向Server发起注册RM的源码4.Client向Server注册RM时的交互源码5.数据源连接...

30分钟了解K8S(30分钟了解微积分)

微服务演进方向o面向分布式设计(Distribution):容器、微服务、API驱动的开发;o面向配置设计(Configuration):一个镜像,多个环境配置;o面向韧性设计(Resista...

SpringBoot条件化配置(@Conditional)全面解析与实战指南

一、条件化配置基础概念1.1什么是条件化配置条件化配置是Spring框架提供的一种基于特定条件来决定是否注册Bean或加载配置的机制。在SpringBoot中,这一机制通过@Conditional...

一招解决所有依赖冲突(克服依赖)

背景介绍最近遇到了这样一个问题,我们有一个jar包common-tool,作为基础工具包,被各个项目在引用。突然某一天发现日志很多报错。一看是NoSuchMethodError,意思是Dis...

你读过Mybatis的源码?说说它用到了几种设计模式

学习设计模式时,很多人都有类似的困扰——明明概念背得滚瓜烂熟,一到写代码就完全想不起来怎么用。就像学了一堆游泳技巧,却从没下过水实践,很难真正掌握。其实理解一个知识点,就像看立体模型,单角度观察总...

golang对接阿里云私有Bucket上传图片、授权访问图片

1、为什么要设置私有bucket公共读写:互联网上任何用户都可以对该Bucket内的文件进行访问,并且向该Bucket写入数据。这有可能造成您数据的外泄以及费用激增,若被人恶意写入违法信息还可...

spring中的资源的加载(spring加载原理)

最近在网上看到有人问@ContextConfiguration("classpath:/bean.xml")中除了classpath这种还有其他的写法么,看他的意思是想从本地文件...

Android资源使用(android资源文件)

Android资源管理机制在Android的开发中,需要使用到各式各样的资源,这些资源往往是一些静态资源,比如位图,颜色,布局定义,用户界面使用到的字符串,动画等。这些资源统统放在项目的res/独立子...

如何深度理解mybatis?(如何深度理解康乐服务质量管理的5个维度)

深度自定义mybatis回顾mybatis的操作的核心步骤编写核心类SqlSessionFacotryBuild进行解析配置文件深度分析解析SqlSessionFacotryBuild干的核心工作编写...

@Autowired与@Resource原理知识点详解

springIOCAOP的不多做赘述了,说下IOC:SpringIOC解决的是对象管理和对象依赖的问题,IOC容器可以理解为一个对象工厂,我们都把该对象交给工厂,工厂管理这些对象的创建以及依赖关系...

java的redis连接工具篇(java redis client)

在Java里,有不少用于连接Redis的工具,下面为你介绍一些主流的工具及其特点:JedisJedis是Redis官方推荐的Java连接工具,它提供了全面的Redis命令支持,且...