【Unity Shader入门精要 第12章】屏幕后处理效果(一)

1. 原理和过程

屏幕后处理是绑定摄像机的,通过抓取当前摄像机渲染的图像作为 SrcTextrue,然后按需依次调用处理接口,对 SrcTexture 进行处理,最后将处理完成的 DstTexture 显示到屏幕上,整个过程的调度通过 C# 脚本完成。

抓取摄像机当前渲染图像使用的接口如下:

OnRenderImage(RenderTexture _src, RenderTexture _dst)

其中:

  • _src为抓取到的当前绑定摄像机的渲染图像
  • _dst为处理结束时的目标纹理

调用的处理接口如下:

Graphics.Blit(Texture _src, RenderTexture _dst)
Graphics.Blit(Texture _src, RenderTexture _dst, Material _mat)
Graphics.Blit(Texture _src, Material _mat, int _passIndex = -1)

其中:

  • _src 为要处理的原始图像
  • _dst 为处理结束后存储到的目标纹理
  • _mat 为本次处理指定的材质,其主要作用是为本次处理提供使用的Shader,需要注意的是,_src会被赋值给该_mat所携带Shader的_MainTex变量,因此在实现Shader时,也需要声明对应名字的变量用于接收原始图像纹理
  • _passIndex 为本次处理指定使用的Pass索引,默认为-1,表示按照顺序依次执行Pass,否则为使用指定索引的Pass

2. 后处理脚本父类

我们可以建立一个后处理的父类,提供所有后处理脚本的基础功能,如检查效果可用性、初始化后处理所用材质等等。

脚本如下:

using UnityEngine;[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class PostEffectBase : MonoBehaviour
{void Start(){CheckResource();}void CheckResource(){bool _supported = CheckDefaultSupported() && CheckSpecificSupported();if (!_supported) OnNotSurported();}/// <summary>/// 用于后处理模块通用设置/// 可被子类重写,因为可能存在某个子类不需要指定条件的情况/// </summary>/// <returns></returns>protected virtual bool CheckDefaultSupported(){return true;}/// <summary>/// 不同后处理子类可以分别实现各自特殊的检查/// </summary>/// <returns></returns>protected virtual bool CheckSpecificSupported(){return true;}/// <summary>/// 不满足后处理启用条件时禁用脚本/// </summary>void OnNotSurported(){enabled = false;}/// <summary>/// 初始化后处理使用的材质和Shader/// </summary>/// <param name="_shader"></param>/// <param name="_material"></param>/// <returns></returns>protected Material CheckShaderAndMaterial(Shader _shader, Material _material){if (null == _shader || !_shader.isSupported) return null;if (null == _material || _material.shader != _shader){_material = new Material(_shader);_material.hideFlags = HideFlags.DontSave;}return _material;}
}

3. 调整亮度、饱和度、对比度

下面的例子中,我们实现一个用于调整屏幕亮度、饱和度以及对比度的后处理效果。

首先,从Shader出发,考虑如何实现对于上述三项的调整:

  1. 对纹理(抓取的屏幕图像)进行采样,得到原始颜色
  2. 调整亮度:用原始颜色乘以亮度系数 _Brightness,即可得到调整后的处理颜色①
  3. 调整饱和度:通过 0.2125 * R + 0.7154 * G + 0.0721 * B 公式对原始颜色进行处理,得到纹理灰度值,然后按照饱和度系数 _Saturation 从灰度值到处理颜色①进行插值,即可得到增加了饱和度变化的处理颜色②
  4. 调整对比度:构建一个 (0.5, 0.5, 0.5) 的对比度为 0 的颜色,按照对比度系数 _Contrast 向处理颜色②进行插值,得到最终的颜色

然后,创建调用后处理的脚本,继承自上文后处理父类:

  1. 为脚本指定所需Shader
  2. 实现OnRenderImage方法,为Shader所需的 _Brightness、 _Saturation、_Contrast 赋值,并调用 Blit 方法执行后处理

测试脚本:

using UnityEngine;public class PostEffect_BrightnessSaturationContrast : PostEffectBase
{public Shader BscShader;public Material BscMat;[Range(0.0f, 3.0f)]public float Brightness = 1;[Range(0.0f, 3.0f)]public float Saturation = 0.5f;[Range(0.0f, 3.0f)]public float Contrast = 0.5f;private void OnRenderImage(RenderTexture src, RenderTexture dest){Material _mat = CheckShaderAndMaterial(BscShader, BscMat);if (null == _mat) Graphics.Blit(src, dest);else{_mat.SetFloat("_Brightness", Brightness);_mat.SetFloat("_Saturation", Saturation);_mat.SetFloat("_Contrast", Contrast);Graphics.Blit(src, dest, _mat);}}
}

测试Shader:

Shader "MyShader/Chapter_12/Chapter_12_BSC_Shader"
{Properties{_MainTex("MainTex", 2D) = "white"{}}SubShader{Pass{Tags{"LightMode" = "ForwardBase"}ZTest AlwaysZWrite OffCull OffCGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdbase#include "UnityCG.cginc"struct v2f{float4 pos : SV_POSITION;float2 uv : TEXCOORD0;};sampler2D _MainTex;float4 _MainTex_ST;fixed _Brightness;fixed _Saturation;fixed _Contrast;v2f vert(appdata_img v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uv = v.texcoord;return o;}fixed4 frag(v2f i) : SV_Target{fixed3 _samplerColor = tex2D(_MainTex, i.uv).rgb;fixed3 _finalColor = _samplerColor * _Brightness;_samplerColor *= _Brightness;//0.2125 * R + 0.7154 * G + 0.0721 * Bfixed _luminance = 0.2125 * _samplerColor.r + 0.7154 * _samplerColor.g + 0.0721 * _samplerColor.b;_finalColor = lerp(float3(_luminance, _luminance, _luminance), _finalColor, _Saturation);_finalColor = lerp(float3(0.5, 0.5, 0.5), _finalColor, _Contrast);return fixed4(_finalColor, 1);}ENDCG}}
}

测试效果:
亮度:
在这里插入图片描述
饱和度:
在这里插入图片描述
对比度:
在这里插入图片描述

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

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

相关文章

【机器学习】Adaboost: 强化弱学习器的自适应提升方法

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 Adaboost: 强化弱学习器的自适应提升方法引言Adaboost基础概念弱学习器与强学习…

【蓝桥杯嵌入式】 第六届国赛

目录 题目 配置 注意事项 代码 - 默写大师 EEPROM读写函数 LED驱动函数 ADC采集 上电初始化 LCD 按键 PWM互补输出 全部代码 hardware.c hardware.h control.c control.h main.c 题目 配置 注意事项 复制LCD的工程&#xff0c;先配置资源 --- 勾选完选项一…

CCIG 2024:合合信息文档解析技术突破与应用前景

目录 背景当前大模型训练和应用面临的问题训练Token耗尽训练语料质量要求高LLM文档问答应用中文档解析不精准 合合信息的文档解析技术1. 具备多文档元素识别能力2. 具备版面分析能力3. 高性能的文档解析4. 高精准、高效率的文档解析文档多板式部分示例 文档解析典型技术难点元素…

案例|开发一个美业小程序,都有什么功能

随着移动互联网的迅猛发展&#xff0c;美业连锁机构纷纷寻求数字化转型&#xff0c;以小程序为载体&#xff0c;提升服务效率&#xff0c;增强客户体验。 线下店现在面临的困境&#xff1a; 客户到店排队时间过长&#xff0c;体验感受差 新客引流难&#xff0c;老用户回头客…

基于EV54Y39A PIC-IOT WA的手指数量检测功能开发(MPLAB+ADC)

目录 项目介绍硬件介绍项目设计开发环境及工程参考总体流程图硬件基本配置光照传感器读取定时器检测逻辑 功能展示项目总结 &#x1f449; 【Funpack3-2】基于EV54Y39A PIC-IOT WA的手指数量检测功能开发 &#x1f449; Github: EmbeddedCamerata/PIC-IOT_finger_recognition 项…

Flutter基础 -- Dart 语言 -- 注释函数表达式

目录 1. 注释 1.1 单行注释 1.2 多行注释 1.3 文档注释 2. 函数 2.1 定义 2.2 可选参数 2.3 可选参数 默认值 2.4 命名参数 默认值 2.5 函数内定义 2.6 Funcation 返回函数对象 2.7 匿名函数 2.8 作用域 3. 操作符 3.1 操作符表 3.2 算术操作符 3.3 相等相关的…

上海亚商投顾:沪指冲高回落 两市成交金额仅剩7000亿

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数昨日冲高回落&#xff0c;午后一度集体翻绿&#xff0c;临近尾盘小幅回升。光伏产业链再度走强&#…

aws 在ecs外部实例上运行gpu负载

参考资料 https://docs.amazonaws.cn/zh_cn/AmazonECS/latest/developerguide/ecs-gpu.htmlhttps://docs.amazonaws.cn/AWSEC2/latest/UserGuide/accelerated-computing-instances.html#gpu-instanceshttps://docs.amazonaws.cn/AWSEC2/latest/UserGuide/install-nvidia-drive…

LeetCode 63.不同路径Ⅱ

思路&#xff1a; 在有障碍物的地方增加一个判断即可 class Solution { public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int dp[105][105];int mobstacleGrid.size();int nobstacleGrid[0].size();for(int i0;i<m;i){for(int j0…

K8s集群之 存储卷 PV PVC

目录 默写 1 如何将pod创建在指定的Node节点上 2 污点的种类(在node上设置) 一 挂载存储​​​​​​​ 1 emptyDir存储卷 2 hostPath存储卷 ①在 node01 节点上创建挂载目录 ② 在 node02 节点上创建挂载目录 ③ 创建 Pod 资源 ④ 在master上检测一下&#xff1a;…

C++ vector 模拟实现

vector的底层也是一个动态数组&#xff0c;他与 string 的区别就是&#xff0c;string 是专门用来存储字符类数据的&#xff0c;为了兼容C语言&#xff0c;使用C语言的接口&#xff0c;在string的动态数组内都会都开一块空间用来存 \0 &#xff0c;而vector则不会。 首先我们要…

【Linux多线程】认识多线程创建线程

文章目录 什么是多线程为什么称linux下的线程是轻量级进程呢&#xff1f; 线程的优点线程的缺点线程异常线程和进程创建线程1.pthread_create2.pthread_self 什么是多线程 进程是正在运行的程序的实例&#xff0c;而线程&#xff08;thread&#xff09;是进程中的一个执行路线…

Springboot邮件发送配置

Springboot邮件发送配置 pom.xml依赖&#xff1a; <dependency><groupId>org.eclipse.angus</groupId><artifactId>jakarta.mail</artifactId><version>2.0.3</version> </dependency> <dependency><groupId>or…

跨域的解决方案

1. 计算机更改跨域 1.C盘->Windows->System32->drivers->etc 2.修改hosts 文件2. Chrome浏览器的跨域设置 操作步骤&#xff1a;1.打开我的电脑——C盘 新建一个文件夹&#xff0c;命名为MyChromeDevUserData2.右键——Chrome——快捷方式——目标&#xff0c;在…

ChatGPT成知名度最高生成式AI产品,使用频率却不高

5月29日&#xff0c;牛津大学、路透社新闻研究所联合发布了一份生成式AI&#xff08;AIGC&#xff09;调查报告。 在今年3月28日—4月30日对美国、英国、法国、日本、丹麦和阿根廷的大约12,217人进行了调查&#xff0c;深度调研他们对生成式AI产品的应用情况。 结果显示&…

ElementUI之el-table标题列中显示el-tooltip

ElementUI之el-table标题列中显示el-tooltip 文章目录 ElementUI之el-table标题列中显示el-tooltip1. el-table标题列中显示el-tooltip2. 实现代码3. 展示效果 1. el-table标题列中显示el-tooltip 在el-table-column标签内添加具名插槽v-slot:header 在el-tooltip标签中使用具…

【几何】输入0-360度任意的角度,求上面直线与椭圆相切点的坐标计算公式

输入0-360度任意的角度,求上面直线与椭圆相切点的坐标计算公式 使用积分计算 使用到的公式有椭圆公式: x 2 a 2 + y 2 b 2 = 1 \frac{x^2}{a^2}+\frac{y^2}{b^2} = 1 a2x2​+b2y2​=1 平面旋转公式 X r = cos ⁡ θ ∗ ( X s − X O ) − sin ⁡ θ ∗ ( Y s − Y O ) + X …

端午节粽子龙舟主题互动趣味小游戏效果是什么

端午三天乐&#xff0c;无论节日当天还是之前&#xff0c;行业商家都可以自己的品牌为主借势营销&#xff0c;趣味活动形式玩法和内容呈现达成多种效果&#xff0c;品牌传播、公众号涨粉、线下互动、商品促销、用户促活等。 在【雨科】平台拥有多款端午节互动小游戏类型&#…

网易狼人杀 设置点击自动发言

我们玩网易狼人杀 刚开始 都会发现 要按住麦克风才能发言 不得不说 相当的麻烦 我们可以点击如下图 右上角这个设置的齿轮 新弹出的设置面板上 勾选这个点击发言 然后 我们只需要 点一下 就可以进入发言状态 然后 再点一下即可停止发言 会方便非常多

zabbix事件告警监控:如何实现对相同部件触发器告警及恢复的强关联

有一定Zabbix使用经验的小伙伴可能会发现&#xff0c;接收告警事件时&#xff0c;其中可能包含着大量不同的部件名&#xff0c;同一部件的事件在逻辑上具有很强关联性&#xff0c;理论上应保持一致的告警/恢复状态&#xff0c;但Zabbix默认并未对它们进行关联&#xff0c;直接后…