56.屏幕后期处理效果-基本实现原理
56.1 知识点
什么是屏幕后期处理效果
屏幕后期处理效果(Screen Post-Processing Effects)是一种在渲染管线的最后阶段应用的视觉效果。它允许你在场景渲染完成后对最终图像进行各种调整和效果处理,从而增强视觉体验。
常见的屏幕后期处理效果包括景深、模糊、色彩调整等。
说人话:
屏幕后期处理效果就是在游戏画面渲染完毕后,通过获取到该画面信息进行额外的效果处理。
Unity中屏幕后期处理效果的基本实现原理
屏幕后期处理效果的实现分为两大核心问题:
如何获取游戏画面渲染完毕后的画面信息
Unity中有三种常用方法来获取渲染纹理:- RenderTexture
- GrabPass
- OnRenderImage
在屏幕后期处理中,主要使用 OnRenderImage 函数获取渲染后的画面信息。
如何为获取到的画面信息添加自定义效果
主要思路是将获取到的游戏画面作为自定义Shader的主纹理,通过Shader实现自定义的视觉效果。
捕获画面的关键——OnRenderImage函数
OnRenderImage 是 Unity 提供的一个在继承自 MonoBehaviour
的脚本中被自动调用的函数(类似生命周期函数)。它会在图像的渲染操作完成后调用,主要作用是捕获当前渲染的画面并对其进行处理。
函数定义
void OnRenderImage(RenderTexture source, RenderTexture destination)
- source: 源渲染纹理,当前渲染得到的屏幕图像存储在该参数中。
- destination: 目标渲染纹理,将经过处理后的图像写入到目标纹理中用于最终的显示。
通过该函数,可以获取当前渲染的游戏画面,并对对应的渲染纹理进行处理,最终显示在屏幕上。
注意事项
- 该函数默认在所有的不透明和透明的 Pass 执行完毕后调用,基于源纹理的修改会对游戏场景中的所有对象产生影响。
- 如果希望只在不透明的 Pass 执行完毕后调用该函数,可在函数前添加特性
[ImageEffectOpaque]
,这样就不会对透明物体产生影响。
在 MonoBehaviour 脚本中实现 OnRenderImage 函数
[ImageEffectOpaque] // 加入该特性,避免影响透明物体
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
// 目前未做任何处理
}
挂载到摄像机上,发现Game窗口黑屏,是因为我们没有在函数中做任何处理,函数中若未对 destination
做处理,画面将显示为黑屏。
实现效果的关键——Graphics.Blit函数
Graphics.Blit 函数用于将一个图像从一个纹理复制到另一个纹理,并在此过程中可以使用着色器对图像进行处理。
函数定义及常用重载
直接复制源纹理到目标纹理
Graphics.Blit(Texture source, RenderTexture dest);
将源纹理直接复制到目标纹理,保持画面正常显示。
使用材质处理源纹理并复制到目标纹理
Graphics.Blit(Texture source, RenderTexture dest, Material mat, int pass = -1);
- source: 源纹理,将传递给
mat
材质中 Shader 的_MainTex
属性。 - mat: 材质,包含处理效果的 Shader。
- pass: 默认值为 -1,表示依次调用 Shader 内的所有 Pass;否则,仅调用指定索引的 Pass。
- source: 源纹理,将传递给
使用示例
直接复制源纹理到目标纹理
[ImageEffectOpaque] private void OnRenderImage(RenderTexture source, RenderTexture destination) { // 将源纹理直接复制到目标纹理,显示正常画面 Graphics.Blit(source, destination); }
使用材质处理源纹理并复制到目标纹理
[ImageEffectOpaque] private void OnRenderImage(RenderTexture source, RenderTexture destination) { // 将源纹理通过材质中的 Shader 进行效果处理后写入目标纹理 Graphics.Blit(source, destination, material); }
通过设置
material
的 Shader,可以实现各种自定义的屏幕后期效果。
总结
屏幕后期处理效果的基本实现原理是利用 OnRenderImage 函数 和 Graphics.Blit 函数,捕获当前屏幕画面并通过 Shader 对该纹理进行自定义处理,最终呈现特殊的视觉效果。
56.2 知识点代码
Lesson56_屏幕后期处理效果_基本实现原理.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson56_屏幕后期处理效果_基本实现原理 : MonoBehaviour
{
public Material material;
void Start()
{
#region 知识点一 什么是屏幕后期处理效果
//屏幕后期处理效果( Screen Post-Processing Effects)是一种在渲染管线的最后阶段应用的视觉效果
//允许你在场景渲染完成后对最终图像进行各种调整和效果处理,从而增强视觉体验
//常见的屏幕后期处理效果有:
//景深、模糊、色彩调整 等等
//说人话:
//屏幕后期处理效果就是当游戏画面渲染完毕后
//通过获取到该画面信息进行额外的效果处理
#endregion
#region 知识点二 Unity中 屏幕后期处理效果的 基本实现原理
//从知识点一中我们可以知道
//想要完成屏幕后期处理效果
//最关键的问题在于
//1.如何获取 游戏画面渲染完毕后的画面信息
//2.如何为 获取到的画面信息添加自定义效果
//只要搞清楚这两点,自然就明白了基本实现原理
//1.如何获取 游戏画面渲染完毕后的画面信息
// 我们之前在学习渲染纹理时学习过
// 在Unity中获取渲染纹理的常用方法有三种
// RenderTexture、GrabPass、OnRenderImage
// 我们在处理屏幕后期处理效果时会使用
// OnRenderImage函数来获取 游戏画面渲染完毕后的画面信息
//2.如何为 获取到的画面信息添加自定义效果
// 主要思路是将获取到的游戏画面作为 自定义Shader的主纹理
// 通过自定义Shader利用捕获的画面来实现自定义效果
#endregion
#region 知识点三 捕获画面的关键——OnRenderImage函数
//OnRenderImage函数
//它是在继承了MonoBehaviour的脚本中能够被自动调用的函数(类似生命周期函数)
//它会在图像的渲染操作完成后调用
//它的固定写法是:
//void OnRenderImage(RenderTexture source, RenderTexture destination)
//第一个参数:源渲染纹理,当前渲染得到的屏幕图像存储在该参数当中
//第二个参数:目标渲染纹理,将经过处理后的图像写入到目标纹理中用于最终的显示
//通过该函数我们便可以得到当前渲染的游戏画面
//并在该函数中对画面对应的渲染纹理进行处理后用于最终显示
//注意:
// 该函数得到的源纹理默认是在所有的不透明和透明的Pass执行完毕后调用的
// 基于该源纹理进行修改会对游戏场景中所有游戏对象产生影响
// 如果你想要在不透明的Pass执行完毕后就调用该函数,只需要在该函数前加上特性
// [ImageEffectOpaque]
// 这样就不会对透明物体产生影响
#endregion
#region 知识点四 实现效果的关键——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的纹理属性用于进行处理(就算没有_MainTex也可能起作用)
// pass参数默认值为-1,表示会依次调用Shader内的所有Pass进行处理,否则,只会调用给定索引的Pass
#endregion
#region 总结
//屏幕后期处理效果的基本实现原理
//就是利用 OnRenderImage函数 和 Graphics.Blit函数
//来获取当前屏幕画面并利用Shader对该纹理进行自定义处理
#endregion
}
//加入该特性 就不会对透明物体产生影响
//[ImageEffectOpaque]
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
// //1.将源纹理直接复制到目标纹理 这样可以让画面正常显示
// Graphics.Blit(source, destination);
//2.将源纹理复制到目标纹理并应用一个材质
//把源纹理 通过 材质球当中的Shader进行效果处理 然后写入到目标纹理中 最终呈现在屏幕上
// source源纹理会被传递给mat材质中Shader中名为_MainTex的纹理属性用于进行处理
// pass参数默认值为-1,表示会依次调用Shader内的所有Pass进行处理,否则,只会调用给定索引的Pass
Graphics.Blit(source, destination, material);
}
}
// 知识点代码块
// 知识点代码块
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com