当前位置: 首页 > news >正文

Unity 引擎做残影效果——2、屏幕后处理方式

Unity实现残影效果


  大家好,我是阿赵。
  这里继续介绍Unity里面做残影的方法。之前介绍了BakeMesh的方法做残影,这一期介绍的是用屏幕后处理的方法做残影。

一、原理

  之前的BakeMesh方法,是真的生成了很多个网格模型在场景里面。如果用后处理做,就没有这个过程。
在这里插入图片描述
在这里插入图片描述

  可以看到,虽然Game视图里面看到了残影,但实际上场景里面只有原理的一个角色的网格模型。
  其实用后处理做残影的方法非常的简单。首先复制一个和主摄像机一样的子摄像机,然后这个摄像机只看角色层,最后,给这个摄像机设置一个RenderTexture作为targetTexture。
在这里插入图片描述

  这样,我们就可以在主摄像机渲染完整的画面的同时,拿到了一个只有角色的RenderTexture。
  然后我们维护一个队列,这个队列保存着过去几帧里面的渲染角色的RenderTexture。至于需要保存多少帧,多久保存一帧,就看各位自己的需要了。
  得到了这个RenderTexture队列之后,剩下的事情就非常简单了。把这个队列传入到后处理的材质里面。
在这里插入图片描述

  这个时候,这几张RenderTexture实际上是下面这样的:
在这里插入图片描述

  后处理的Shader很简单,就是把这几张Texture按照先后顺序,用过不同的透明度去合成在一起:
在这里插入图片描述

  这样,残影的效果就做出来了。如果想修改残影的颜色,也是直接在后处理的时候,给残影的Texture乘以一个颜色就行了。

二、优缺点

1、优点

  对比起BakeMesh方法,这个后处理的方式,并不需要渲染多很多个角色的网格,只是需要多一个摄像机渲染多一次所有需要残影的角色而已。我们可以做一个优化,当某个角色需要做残影,就把它设置为专门的Layer,让这个残影摄像机能渲染到。平时没有需要残影的角色的时候,这个摄像机是什么都看不到。
  然后,场景里面就算有非常多的角色同时残影,最多也就是每个角色多渲染一次就够了,对于渲染方面的性能消耗还是很友好的。就是牺牲点内存,把这张RenderTexture复制并保存在内存里面。这个消耗我觉得并不是很大。
  如果想在这个基础上做其他效果,也是很轻松的,比如想对残影做模糊,或者Bloom,或者校色,其实就是对保存的这几张Texture做处理就行了,可以实现的效果非常多。

2、缺点

  由于是保存多张Texture作为合成残影的基础,所以究竟保存多少张合适,是一个问题。如果保存得少,那么残影的效果不是很明显,如果保存得多,内存的占用也会比较多。

三、代码

由于是Demo,所以写得比较简单一点,没有做优化,大家看个原理吧。

1、C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MoveImageEffectCtrl : MonoBehaviour
{// Start is called before the first frame updateprivate List<Texture> rtList;public Camera subCam;public bool isMove = false;private Texture2D blackTex;public Material mat;public int spaceTime = 10;private int countTime = 0;private Vector3 oldPos;public GameObject role;void Start(){CreateBlackTexture();}// Update is called once per framevoid Update(){countTime++;if (countTime % spaceTime == 0){CheckMove();}}private void CheckMove(){if (Vector3.Distance(oldPos, role.transform.position) > 0){isMove = true;RenderTexture camTarget = subCam.targetTexture;RenderTexture rt = RenderTexture.GetTemporary(camTarget.width, camTarget.height);CopyRender(camTarget, rt);AddToRTList(rt);oldPos = role.transform.position;}else{isMove = false;}}private void CopyRender(RenderTexture source, RenderTexture destination){Graphics.Blit(source, destination);}private void CreateBlackTexture(){blackTex = new Texture2D(128, 128);for (int i = 0; i < 128; i++){for (int j = 0; j < 128; j++){blackTex.SetPixel(i, j, Color.clear);}}blackTex.Apply();}private void AddToRTList(Texture rt){if (rtList == null){rtList = new List<Texture>();}rtList.Add(rt);if (rtList.Count > 5){for (int i = 0; i < rtList.Count - 5; i++){Texture tex = rtList[0];rtList.RemoveAt(0);if (tex is RenderTexture){RenderTexture.ReleaseTemporary((RenderTexture)tex);}}}}private void SetTexToMat(){if (isMove == false){mat.SetFloat("_isMove", 0);}else{mat.SetFloat("_isMove", 1);for (int i = 0; i < 5; i++){string key = "_Tex" + (i + 1);Texture tex = GetTexById(i);mat.SetTexture(key, tex);}}}private Texture GetTexById(int id){if (rtList == null || rtList.Count <= id){return blackTex;}else{return rtList[id];}}private void OnRenderImage(RenderTexture source, RenderTexture destination){SetTexToMat();if(isMove){Graphics.Blit(source, destination, mat);}else{Graphics.Blit(source, destination);}}
}

2、Shader

Shader "Unlit/MoveEffectCom"
{Properties{_MainTex ("Texture", 2D) = "white" {}_Tex1("Tex1",2D) = "black"{}_Tex2("Tex2",2D) = "black"{}_Tex3("Tex3",2D) = "black"{}_Tex4("Tex4",2D) = "black"{}_Tex5("Tex5",2D) = "black"{}_isMove("isMove",Float) = 0}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;sampler2D _Tex1;sampler2D _Tex2;sampler2D _Tex3;sampler2D _Tex4;sampler2D _Tex5;float _isMove;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);UNITY_TRANSFER_FOG(o,o.vertex);return o;}half4 frag (v2f i) : SV_Target{// sample the texturehalf4 col = tex2D(_MainTex, i.uv);if (_isMove > 0){half4 addTex1 = tex2D(_Tex1, i.uv);half4 addTex2 = tex2D(_Tex2, i.uv);half4 addTex3 = tex2D(_Tex3, i.uv);half4 addTex4 = tex2D(_Tex4, i.uv);half4 addTex5 = tex2D(_Tex5, i.uv);half3 rgb = col.rgb + saturate(addTex1.rgb*addTex1.a*0.6f + addTex2.rgb*addTex2.a*0.5f + addTex3.rgb*addTex3.a*0.3f + addTex4.rgb*addTex4.a*0.2f + addTex5.rgb*addTex5.a*0.1f)*(1-col.a)*float3(1,0,0);rgb = saturate(rgb);col = half4(rgb, col.a);}return col;}ENDCG}}
}

相关文章:

Unity 引擎做残影效果——2、屏幕后处理方式

Unity实现残影效果 大家好&#xff0c;我是阿赵。 这里继续介绍Unity里面做残影的方法。之前介绍了BakeMesh的方法做残影&#xff0c;这一期介绍的是用屏幕后处理的方法做残影。 一、原理 之前的BakeMesh方法&#xff0c;是真的生成了很多个网格模型在场景里面。如果用后处理做…...

考研算法38天:反序输出 【字符串的翻转】

题目 题目收获 很简单的一道题&#xff0c;但是还是有收获的&#xff0c;我发现我连scanf的字符串输入都忘记咋用了。。。。。我一开始写的 #include <iostream> #include <cstring> using namespace std;void deserve(string &str){int n str.size();int…...

“深入解析JVM:探秘Java虚拟机的工作原理“

标题&#xff1a;深入解析JVM&#xff1a;探秘Java虚拟机的工作原理 摘要&#xff1a;本文将深入探讨Java虚拟机&#xff08;JVM&#xff09;的工作原理&#xff0c;包括类加载、内存管理、垃圾回收、即时编译等关键概念。通过详细解析JVM的各个组成部分&#xff0c;读者将能够…...

[Flask]SSTI1

根据题目提示&#xff0c;这关应该是基于Python flask的模版注入&#xff0c;进入靶场环境后就是一段字符串&#xff0c;而且没有任何提示&#xff0c;有点难受&#xff0c;主要是没有提示注入点 随机尝试一下咯&#xff0c;首先尝试一下guest&#xff0c;GET传参 但是没有反应…...

Object Map 的相互转换

学生业务对象定义&#xff1a;Student Student student new Student(); student.setId(1L); student.setName("令狐冲") student.setAge(10) 第一种&#xff1a;通过Alibaba Fastjson实现 pom.xml 文件依赖 <dependency><groupId>com.alibaba</g…...

VS+Qt环境下解决中文乱码问题

目录 原因解决方案总结 原因 使用VSQt出现中文乱码的情况一般都是给控件添加中文文本时出现&#xff0c;而控件需要的字符串类型是QString&#xff0c;默认是utf-8。在 Visual Studio 中&#xff0c;源代码文件的默认执行字符集可能是 Windows 默认的 ANSI 字符集&#xff0c;…...

互联网摸鱼日报(2023-08-08)

互联网摸鱼日报(2023-08-08) 36氪新闻 宝洁、欧莱雅、联合利华加大广告预算投入&#xff1a;越萧条&#xff0c;要越营销&#xff1f; 把智能手机的“高端货”装进汽车&#xff0c;厂商的脑洞越来越大了 王一博《热烈》票房破7亿&#xff0c;街舞是一门怎样的生意&#xff1…...

NTT DATA利用相干伊辛机模拟基因组组装和疾病治疗的潜力

​ &#xff08;图片来源&#xff1a;网络&#xff09; 7月20日&#xff0c;日本领先的IT服务提供商和行业咨询公司NTT DATA宣布完成了一个使用量子计算优化基因组组装过程的项目。这是量子计算应用于医疗保健和生命科学行业中的一个里程碑。 本项目通过比较量子和非量子计算方…...

哈希表语法(转载自用)

哈希表 哈希表是一种很常见的数据结构,我现在平时刷算法题一般使用C++刷(不要问我为什么,懂的都懂)。C++关于哈希表有很多数据结构,平时使用的比较多的有unordered_set 跟 unordered_map。其中unordered_map 存储的是键值对。 其实我们在某些情况下可以使用数组构建哈希表…...

打破界限,图文档与物料清单完美互联

在现代企业的产品开发过程中&#xff0c;图文档和物料清单是不可或缺的重要信息。然而&#xff0c;由于数据来源多样、格式繁杂&#xff0c;图文档与物料清单之间的信息传递往往存在障碍。而PDM系统&#xff08;Product Data Management&#xff0c;产品数据管理&#xff09;的…...

【电机绘图】:插补算法(一)—直线插补—逐点比较法

今日介绍学习一种使用电机作画、绘图、加工零件时需要使用的算法 &#xff1a; 插补算法 本文提供直线插补的概念基础&#xff0c;基本思路分析&#xff0c;C语言实现等&#xff0c;代码会直接贴出&#xff01; 插补算法是指在数值计算或数据处理中&#xff0c;根据已有的数据…...

16-2_Qt 5.9 C++开发指南_使用样式表Qss自定义界面

进行本篇介绍学习前&#xff0c;请先参考链接01_1_Qt工程实践_Qt样式表Qss&#xff0c;后再结合本篇进行融合学习如何使用样式表定义界面。 文章目录 1. Qt样式表2. Qt样式表句法2.1 一般句法格式2.2 选择器 (selector)2.3 子控件&#xff08;sub-controls&#xff09;2.4 伪状…...

chatgpt openai API报错openai.error.APIConnectionError

openai.error.APIConnectionError: Error communicating with OpenAI: 报错信息无用方案问题查看urllib3版本方法 可行方案法1法2&#xff1a;自己找包安装 报错信息 raise error.APIConnectionError( openai.error.APIConnectionError: Error communicating with OpenAI: HTT…...

【果树农药喷洒机器人】Part1:研究现状分析以及技术路线介绍

本专栏介绍&#xff1a;付费专栏&#xff0c;持续更新机器人实战项目&#xff0c;欢迎各位订阅关注。 关注我&#xff0c;带你了解更多关于机器人、嵌入式、人工智能等方面的优质文章&#xff01; 文章目录 一、项目背景二、国内外研究现状2.1 国内研究现状2.2 国外研究现状 三…...

QT-QTablewidget 设置选中某一行

要在 QTableWidget 中设置选中的行&#xff0c;可以使用 setCurrentItem() 函数来设置当前的 QTableWidgetItem。你可以通过调用 QTableWidget 的 item() 函数获得指定行和列的 QTableWidgetItem&#xff0c;然后通过将其传递给 setCurrentItem() 函数来设置选中的行。 下面是…...

[shell] 删除指定文件状态变更之前的文件及文件夹示例

参考文件 Linux查找某个指定时间要求的文件 脚本示例 #!/bin/bash# 删除指定时间之前文件&#xff0c;单位&#xff1a;分钟 ago75# 监控路径,必须使用使用绝对路径&#xff0c;防止意外删除重要文件 monitoring_path"/home/dev/test/test" # 使用find命令查找75分…...

代码中 isEmpty 和 isBlank 的区别

isEmpty系列 StringUtils.isEmpty() 是否为空. 可以看到 " " 空格是会绕过这种空判断,因为是一个空格,并不是严格的空值,会导致 isEmpty(" ")false tringUtils.isEmpty(null) true StringUtils.isEmpty("") true StringUtils.isEmpty(" …...

为什么要选择文件传输软件?有哪些最佳高速文件传输软件?

是否经历过这样的场景&#xff0c;正在努力地完成工作任务&#xff0c;但是由于制作的数据无法及时传送给合作伙伴&#xff0c;工作流程被打断了&#xff1f;这听起来很令人沮丧&#xff0c;对吧&#xff1f;可是&#xff0c;这种情况在现实中并不罕见。 因此&#xff0c;需要…...

aardio + customPlus 显示图片演示

看效果&#xff1a; 上代码&#xff1a; import win.ui; /*DSG{{*/ var winform win.form(text"aardio customPlus 显示图片演示 by 光庆";right927;bottom607) winform.add( button{cls"button";text"下一页";left664;top536;right794;bott…...

收集到大量的名片怎么转为excel?

来百度APP畅享高清图片 参加完展会或集体会议&#xff0c;是不是收了一大堆名片&#xff0c;保管起来超级麻烦&#xff0c;还容易丢三落四&#xff1f;别急&#xff0c;我们有办法&#xff01;把名片转成电子版保存到电脑上就完美啦&#xff01;但要是名片数量有点多&#xff0…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...