屏幕后期处理

news/2024/11/13 12:27:32/

1、屏幕后期处理效果

屏幕后期处理效果( Screen Post-Processing Effects)是一种在渲染管线的最后阶段应用的视觉效果,允许在场景渲染完成后对最终图像进行各种调整和效果处理,从而增强视觉体验
常见的屏幕后期处理效果有:景深、模糊、色彩调整 等等

2、Unity中 屏幕后期处理效果的 基本实现原理

想要完成屏幕后期处理效果
最关键的问题在于

  • 如何获取 游戏画面渲染完毕后的画面信息
  • 如何为 获取到的画面信息添加自定义效果

只要搞清楚这两点,自然就明白了基本实现原理

(1)如何获取 游戏画面渲染完毕后的画面信息
 在Unity中获取渲染纹理的常用方法有三种:RenderTexture、GrabPass、OnRenderImage
在处理屏幕后期处理效果时会使用OnRenderImage函数来获取 游戏画面渲染完毕后的画面信息

(2)如何为 获取到的画面信息添加自定义效果
主要思路是将获取到的游戏画面作为 自定义Shader的主纹理,通过自定义Shader利用捕获的画面来实现自定义效果

3、捕获画面的关键——OnRenderImage函数

OnRenderImage函数
它是在继承了MonoBehaviour的脚本中能够被自动调用的函数(类似生命周期函数),它会在图像的渲染操作完成后调用
它的固定写法是:

void OnRenderImage(RenderTexture source, RenderTexture destination)
第一个参数:源渲染纹理,当前渲染得到的屏幕图像存储在该参数当中
第二个参数:目标渲染纹理,将经过处理后的图像写入到目标纹理中用于最终的显示

通过该函数我们便可以得到当前渲染的游戏画面,并在该函数中对画面对应的渲染纹理进行处理后用于最终显示

注意:
该函数得到的源纹理默认是在所有的不透明和透明的Pass执行完毕后调用的,基于该源纹理进行修改会对游戏场景中所有游戏对象产生影响,如果你想要在不透明的Pass执行完毕后就调用该函数,只需要在该函数前加上特性 [ImageEffectOpaque] 这样就不会对透明物体产生影响

//加入该特性 就不会对透明物体产生影响
//[ImageEffectOpaque]
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{1.将源纹理直接复制到目标纹理//Graphics.Blit(source, destination);//把源纹理 通过 材质球当中的Shader进行效果处理 然后写入到目标纹理中 最终呈现在屏幕上Graphics.Blit(source, destination, material);
}

4、实现效果的关键——Graphics.Blit函数

Graphics.Blit函数用于将一个图像从一个纹理复制到另一个纹理,同时可以在这个过程中用着色器对图像进行处理,它有很多重载,主要讲解几个常用的:

(1)将源纹理直接复制到目标纹理

Graphics.Blit(Texture source, RenderTexture dest)

(2)将源纹理复制到目标纹理并应用一个材质

Graphics.Blit(Texture source, RenderTexture dest, Material mat, int pass = -1);source源纹理会被传递给mat材质中Shader中名为_MainTex的纹理属性用于进行处理
pass参数默认值为 - 1,表示会依次调用Shader内的所有Pass进行处理,否则,只会调用给定索引的Pass

5、屏幕后处理基类

补充:

(1)Shader.isSupported
通过获取Shader对象中的isSupported属性判断Shader在目标平台和硬件上是否能正确运行

(2)[ExecuteInEditMode]特性
用于使脚本在编辑器模式下也能执行

(3)[RequireComponent(typeof(组件名))]特性
指定某个脚本所依赖的组件,它确保当你将脚本附加到游戏对象时,所需的组件也会自动添加到该游戏对象中,如果这些组件已经存在,它们不会被重复添加,因为后处理脚本一般添加到摄像机上,因此我们用于依赖摄像机

(4)材质球中的 HideFlags 枚举
从材质球对象中可以点出 HideFlags 枚举

  • HideFlags.None: 对象是完全可见和可编辑的。这是默认值。
  • HideFlags.HideInHierarchy: 对象在层级视图中被隐藏,但仍然存在于场景中。
  • HideFlags.HideInInspector: 对象在检查器中被隐藏,但仍然存在于层级视图中。
  • HideFlags.DontSaveInEditor: 对象不会被保存到场景中。适用于编辑器模式,不会影响播放模式。
  • HideFlags.NotEditable: 对象在检查器中是只读的,不能被修改。
  • HideFlags.DontSaveInBuild: 对象不会被包含在构建中。
  • HideFlags.DontUnloadUnusedAsset: 对象在资源清理时不会被卸载,即使它没有被引用。
  • HideFlags.DontSave: 对象不会被保存到场景中,不会在构建中保存,也不会在编辑器中保存。这是 DontSaveInEditor | DontSaveInBuild | DontUnloadUnusedAsset 的组合。

    如果想要设置枚举满足多个条件 直接多个枚举 进行位或运算即可 |

为什么要实现屏幕后处理基类

原因一:为了实现屏幕后期处理效果,每次都需要做的事情一定是

  • 实现一个继承子MonoBehaviour的自定义C#脚本
  • 关联对应的材质球或者Shader
  • 实现OnRenderImage函数
  • 在OnRenderImage函数中使用Graphics.Blit函数

那么这些共同点我们完全可以抽象到一个基类中去完成,以后只需要在子类中实现各自的基本逻辑即可

原因二:可以在基类中用代码动态创建材质球,不需要为每个后处理效果都手动创建材质球,只需要在Inspector窗口关联对应使用的Shader即可

原因三:在进行屏幕后处理之前,往往需要检查一系列条件是否满足,比如:
当前平台是否支持当前使用的Unity Shader,我们可以在基类中进行判断,避免每次书写相同逻辑

注意:
在一些老版本中,你可能还会在基类中判断目标平台是否支持屏幕后处理和渲染纹理,一般通过Unity中的SystemInfo类判断,该类可以用于确定底层平台和硬件相关的功能是否被支持
官方说明:https://docs.unity.cn/cn/2022.3/ScriptReference/SystemInfo.html

using System.Collections;
using System.Collections.Generic;
using UnityEngine;[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class PostEffectBase : MonoBehaviour
{// 屏幕后处理效果会使用的Shaderpublic Shader shader;// 动态创建的材质球private Material _material;protected Material material {get {if (shader == null || !shader.isSupported)return null;else {if (_material != null && _material.shader == shader)return _material;// 用支持的 Shader 动态创建一个材质球用于渲染_material = new Material(shader);_material.hideFlags = HideFlags.DontSave;return _material;}}}protected virtual void OnRenderImage(RenderTexture source, RenderTexture destination) {UpdateProperty();if (material != null)Graphics.Blit(source, destination, material);elseGraphics.Blit(source, destination);}protected virtual void UpdateProperty() {}
}


http://www.ppmy.cn/news/1546301.html

相关文章

App渠道来源追踪方案全面分析(iOS/Android/鸿蒙)

一、App 渠道来源追踪概述 渠道来源统计/追踪,其原理都可以称之为归因,归因是用于判断用户在什么原因、什么时间、什么场景下载了 App,以及打通他们在激活 App 后进行的一系列操作(比如注册、付费、加购等)。 渠道来…

你对安装在自己网站上的wordpress插件了解吗?

有不少用wordpress建站的人,喜欢用插件实现一些功能,使用插件是可以很方便的实现一些功能,但是,使用插件也会带来不少的问题。关于这个,这里就不讲了,网上可以搜索出一堆相关的内容来,这里只提出…

修改elementUI等UI组件样式的5种方法总结,哪些情况需要使用/deep/, :deep()等方式来穿透方法大全

文章目录 方法 1:全局修改样式示例:修改 `ElMessage` 的背景色和字体颜色方法 2:修改特定类型的 `ElMessage` 样式-全局-不需要穿透示例:修改 `ElMessage` 成功类型的样式方法 3:通过 Scoped CSS 在组件内部修改-局部-不需要穿透方法 4:使用 JavaScript 动态修改样式-不需…

STM32外设之SPI的介绍

### STM32外设之SPI的介绍 SPI(Serial Peripheral Interface)是一种高速的,全双工,同步的通信总线,主要用于EEPROM、FLASH、实时时钟、AD转换器等外设的通信。SPI通信只需要四根线,节约了芯片的管脚&#x…

【dvwa靶场:XSS系列】XSS (DOM) 低-中-高级别,通关啦

一、低级low 拼接的url样式&#xff1a;​​​​​​​ http://127.0.0.1/dvwa/vulnerabilities/xss_d/?default 拼接的新内容 <script>alert("假客套")</script> 二、中级middle 拼接的url样式&#xff1a;​​​​​​​ http://127.0.0.1/dvwa/vuln…

一文读懂【CSR社会责任报告】

CSR社会责任报告是企业将其履行社会责任的理念、战略、方式方法&#xff0c;以及其经营活动对经济、环境、社会等领域造成的直接和间接影响、取得的成绩及不足等信息&#xff0c;进行系统的梳理和总结&#xff0c;并向利益相关方进行披露的方式。以下是对CSR社会责任报告及其报…

LeetCode34:在排序数组中查找元素第一个和最后一个位置

原题地址&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target&#xff0c;返回 [-1, -1]。 你必须…

jQuery UI 使用

jQuery UI 使用 jQuery UI 是一个建立在 jQuery JavaScript 库之上的用户界面交互、特效、小部件和主题的库。它提供了一系列的交互组件,如拖动、排序、选择等,以及小部件,如自动完成、日期选择器、滑块等。此外,jQuery UI 还提供了一套主题,使得开发者可以轻松地定制应用…