利用脚本和Shader制作屏幕后处理效果

news2025/3/29 10:26:28

一、屏幕后处理的实现原理

该屏幕后处理的原理是将渲染完成后的屏幕纹理通过脚本和Shader完成一些操作,然后实现各种屏幕效果

而实现屏幕后处理效果的主要操作就是获得当下渲染完成后的屏幕图像,其中unity提供了一个函数用于获取此图像——OnRenderImage ( )

 private void OnRenderImage(RenderTexture src,RenderTexture dest) { ... }

当在脚本中声明此函数后,Unity会把当前渲染完成后的图像存储在src源渲染纹理中,通过函数中的一系列操作后(该函数内操作是我们自定义的),再把目标渲染纹理存储在dest渲染纹理中,dest最终会被显示到屏幕上

然后在OnRenderImage函数中可以利用Graphics.Blit函数来完成对渲染后的屏幕图像的操作

Graphics.Blit(Texture src , RenderTexture dest , Material Mat);

Graphics.Blit(Texture src , RenderTexture dest , Material Mat , int pass=-1);

Graphics.Blit(src, dest, Mat);

src为源纹理,dest为处理后的纹理最后会显示到屏幕上

mat是所使用的材质,该材质会利用相应的Sahder代码对源纹理进行屏幕后处理效果的实现

其中src源纹理会被传入到Shader的_MainTex属性中,所以我们就可以利用Sahder对_MainTex属性进行修改来实现屏幕后处理的效果

同时参数Pass的默认值为-1,表示将会依次调用Shader内的所有Pass

二、关于黑白阈值的屏幕后处理效果实现

首先创建一个脚本,挂载到摄像机上

在脚本中添加OnRenderImage函数

private void OnRenderImage(RenderTexture src , RenderTexture dest)

{

        Graphics.Blit(src,dest,Mat)

}

其中Mat代表的材质还未指定,可以在脚本中添加一个公共的Sahder用于存放所需要的Shader,然后通过该Shader创建对应的材质球(Material _newmat = new Material( PostProcessingShader );

public Shader PostProcessingShader;

Material _newmat = new Material( PostProcessingShader ); //通过Shader创建材质球

然后添加一个关于Mat的Get/Set属性访问器(public Material Mat),然后在public Material Mat中设置 private Material mat 的值

当在OnRenderImage函数中使用到Mat时,此时就会进入到public Material Mat的Get方法中读取到mat的值,从而返回给OnRenderImage函数该值。具体如下方所示:

private Material mat;

public Material Mat
{
    get
    {  


        //当mat为空时
        if(mat==null)
        {
            //为指定的Shader新建一个材质球
            Material _newmat = new Material( PostProcessingShader );

            //材质球隐藏并且不保存
            _newmat.hideFlags = HideFlags.HideAndDontSave;
            mat = _newmat;
            //将新建的材质球返回给Mat
            return mat;  //读取并返回值
        }


        //mat不为空
        else
        {
            return mat;   //读取并返回值
        }
    }
}


关于Get/Set属性访问器的具体用法和原理参考:

Unity-Get/Set属性访问器详解_unity get set-CSDN博客

C#的属性:get、set_c# get =>-CSDN博客

Get/Set属性访问器中使用get方法中读取值,set方法设置值。在set方法中可以对值的设置进行限制,起到一定的安全作用


接着在 "PostProcessingShader" 的Shader代码中来完成屏幕后处理效果,例如黑白阈值

接上文,src源纹理会通过Graphics.Blit函数传入到Shader的_MainTex属性中,所以在Shader可以通过uv坐标采样_MainTex得到源纹理的fixed4 类型的颜色值

对于黑白阈值的实现,可以根据采样后的 col.r 与一个滑杆值进行step函数的计算

step(a,b)    当a<=b时 , return 1;  else return 0

滑杆值:_BW("BW",Range(0,1))=0

采样贴图后的值:fixed4 col = tex2D(_MainTex, i.uv);

step(col.r , _BW);      //step(a,b) 当a<=b时,return 1; else return 0

但是此时Shader创建的材质球不会被暴漏出来,所以材质球中_BW的滑杆属性不能被调节

所以此时只能在脚本代码中对_BW参数进行调节

  • 先在脚本中设置一个变量,用于控制黑白阈值   [Range(0,1)] public float bw;
  • 然后通过SetFloat在脚本中更改Shader中_BW属性的值
  • Mat.SetFloat("_BW",bw);

C#脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static System.Net.WebRequestMethods;
using UnityEngine.UI;

//在编辑器模式下也可运行此脚本
[ExecuteInEditMode]

public class Postprocessing : MonoBehaviour
{
    public Shader PostProcessingShader;

    //在脚本中设置一个变量,用于控制黑白阈值
    [Range(0,1)]public float bw;

    private Material mat;

    public Material Mat
    {
        get
        {  
            //当mat为空时
            if(mat==null)
            {
                //为指定的Shader新建一个材质球
                Material _newmat = new Material(PostProcessingShader);

                //材质球隐藏并且不保存
                _newmat.hideFlags = HideFlags.HideAndDontSave;
            
                mat = _newmat;
                //将新建的材质球返回给Mat
                return mat;
            }
            //mat不为空
            else
            {
                return mat;
            }
        }
    }

    //Unity在图像渲染完成后对图像进行修改,需要对OnRenderImage() 进行重写
    //OnRenderImage在图像渲染完成之后被调用,因此可以用来添加屏幕的后处理效果。
    //输入的图片 RenderTextrure source, 输出的图片是 RenderTexture destination.
    //如果要对这个方法进行重写,必须要要加上 Graphic.Blit方法。
    //src为原始图像,dest为修改后的图像
    private void OnRenderImage(RenderTexture src,RenderTexture dest)
    {
        Mat.SetFloat("_BW",bw);
        //src图像须传入到Mat材质Shader中,然后Shader使用MainTex来获取此图像
        Graphics.Blit(src, dest, mat);
    }
}

Shader代码:

Shader "Hidden/PostProcessing"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}

        _BW("BW",Range(0,1))=0
    }
    SubShader
    {
        // No culling or depth
        Cull Off

        //深度写入关闭,因为深度写入会导致画面出错
        ZWrite Off

        //使每一帧的图像都被渲染到屏幕上
        ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag

            #include "UnityCG.cginc"

            float _BW;
            sampler2D _MainTex;

            fixed4 frag (v2f_img i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                // just invert the colors  反向颜色值然后输出

                // return step(col,0.5);  fixed4(step(col.r,0.5),step(col.g,0.5),step(col.b,0.5),step(col.a,0.5))

                // step(a,b) 当a<=b时,return 1; else return 0;

                //在脚本代码中修改_BW值
                return step(col.r,_BW);
            }
            ENDCG
        }
    }
}

【太妃糖耶】新作上线,快来看看!

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

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

相关文章

【银河麒麟系统常识】命令:uname -m(查看系统架构)

命令&#xff1a; uname -m 功能 常用的 Linux/Unix 终端命令&#xff0c;用于显示当前系统的硬件架构&#xff1b; 返回 返回系统的CPU架构类型&#xff0c;用于判断软件兼容性&#xff1b; 输出结果架构说明常见设备x86_64Intel/AMD 64位 CPU主流 PC、服务器aarch64ARM 64位 …

3.1.2 内存池

文章目录 3.1.2 内存池1. 什么是内存池2. 内存管理1. 定长2. 不定长3. jemalloc4. tcmalloc 3.1.2 内存池 1. 什么是内存池 内存池&#xff08;Memory Pool&#xff09; 是一种 预先分配 一块大内存&#xff0c;然后按需分配和回收 其中小块内存的技术。它的本质是管理一块连续…

基于SpringBoot + Vue 的餐厅点餐管理系统

SpringBootVue餐厅点餐管理系统 技术框架 后端&#xff1a;springboot mybatisPlus前端&#xff1a;Vue2 elementUI数据库&#xff1a;mysql项目构建工具&#xff1a;maven 数据库表 14张 角色及功能 管理员&#xff1a;登录、用户管理、餐桌信息管理、菜品类型管理、菜…

【博客节选】再谈Unity 的 root motion

节选自 【Unity实战笔记】第二十三 root motion变更方向攻击 &#xff08;OnStateMove rootmotion rigidbody 使用的一些问题&#xff09; 小伙伴们应该对root motion非常困惑&#xff0c;包括那个bake into pose。 当xz bake into pose后&#xff0c;角色攻击动画与父节点产…

26考研——栈、队列和数组_栈(3)

408答疑 文章目录 一、栈1、栈&#xff08;Stack&#xff09;的概念和特点定义术语操作特性示例直观理解栈的基本操作初始化栈判断栈是否为空入栈操作出栈操作读取栈顶元素销毁栈 栈的数学性质 2、栈的顺序存储结构顺序栈的定义栈顶指针初始化注意事项 共享栈共享栈的操作共享栈…

基于 mxgraph 实现流程图

mxgraph 可以实现复杂的流程图绘制。mxGraph里的Graph指的是图论(Graph Theory)里的图而不是柱状图、饼图和甘特图等图(chart)&#xff0c;因此想找这些图的读者可以结束阅读了。 作为图论的图&#xff0c;它包含点和边&#xff0c;如下图所示。 交通图 横道图 架构图 mxGrap…

动态路由机制MoE专家库架构在多医疗AI专家协同会诊中的应用探析

随着医疗人工智能技术的飞速进步,AI在医学领域的应用日益增多,尤其是在复杂疾病的诊断和治疗中,AI技术的应用带来了巨大的潜力。特别是动态路由机制混合专家(Mixture of Experts,MoE)架构,因其灵活、高效的特点,正逐渐成为实现多AI专家协同会诊的关键技术。通过将多个不…

双工通信:WebSocket服务

&#xff08;一&#xff09;WebSocket概述 WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c; 并进行双向数据传输 注意;Websocket也只能由客户端先握…

洪水灌溉算法 + 总结

文章目录 floodfill算法图像渲染题解代码 岛屿数量题解代码 岛屿的最大面积题解代码 被围绕的区域题解代码 太平洋大西洋水流问题题解代码 扫雷游戏题解代码 衣橱整理题解代码 总结 floodfill算法 1. 寻找相同性质的联通块&#xff0c;可以使用dfs或者bfs解决&#xff0c;比如…

LangChain4j(1):初识LangChain4j

1 什么是LangChain和LangChain4j LangChain是一个大模型的开发框架&#xff0c;使用LangChain框架&#xff0c;程序员可以更好的利用大模型的能力&#xff0c;大大提高编程效率。如果你是一个lava程序员&#xff0c;那么对LangChain最简单直观的理解就是&#xff0c;LangChain…

Photoshop 2025安装包下载及Photoshop 2025详细图文安装教程

文章目录 前言一、Photoshop 2025安装包下载二、Photoshop 2025安装教程1.解压安装包2.运行程序3.修改安装路径4.设安装目录5.开始安装6.等安装完成7.关闭安装向导8.启动软件9.安装完成 前言 无论你是专业设计师&#xff0c;还是初涉图像处理的小白&#xff0c;Photoshop 2025…

SQL Server安装程序无法启动:系统兼容性检查失败

问题现象&#xff1a; 运行 SQL Server 2022 安装程序时&#xff0c;提示 “硬件或软件不满足最低要求”&#xff0c;安装向导直接退出或无法继续。 快速诊断 操作系统版本检查&#xff1a; # 查看 Windows 版本&#xff08;需 20H2 或更高&#xff09; winver 支持的系统&…

期权合约作废的话,权利金和保证金会退还么?

在期权交易中&#xff0c;权利金是否可以退回&#xff0c;主要取决于期权的交易情况和合约条款。 期权作废的三种情形 一般来说期权作废一共有三种情况&#xff0c;分别是到期没有行权、主动放弃或者是标的退市了。 第一种是到期未行权&#xff0c;一般来说值得都是虚值期权&…

MIPI计算ECC和CRC工具介绍

一、MIPI简介 MIPI联盟&#xff0c;即移动产业处理器接口&#xff08;Mobile Industry Processor Interface 简称MIPI&#xff09;联盟。MIPI&#xff08;移动产业处理器接口&#xff09;是MIPI联盟发起的为移动应用处理器制定的开放标准和一个规范。MIPI官网https://mipi.org/…

医院管理系统(源码)分享

「医院管理系统&#xff08;源码&#xff09; 源码&#xff1a; https://pan.quark.cn/s/b6e21488fce3 第1章 绪论 1.1 项目背景 随着计算机科学的迅猛发展和互联网技术的不断推进&#xff0c;人们的生活方式发生了巨大的变化&#xff0c;同时也推动了整个软件产业的发展。把…

使用Geotools从DEM数据中读取指定位置的高程实战

目录 前言 一、GridCoverage2D对象介绍 1、GridCoverage2D的属性 2、GridCoverage2D核心方法 3、GridCoverage2D中的高级操作 二、指定位置的高程获取 1、存储原理 2、相关属性的获取 3、获取高程的方法 三、总结 前言 在地理信息科学领域&#xff0c;高程数据是至关重…

STM32F103_LL库+寄存器学习笔记05 - GPIO输入模式,捕获上升沿进入中断回调

导言 GPIO设置输入模式后&#xff0c;一般会用轮询的方式去查看GPIO的电平状态。比如&#xff0c;最常用的案例是用于检测按钮的当前状态&#xff08;是按下还是没按下&#xff09;。中断的使用一般用于计算脉冲的频率与计算脉冲的数量。 项目地址&#xff1a;https://github.…

直播预告 | TDgpt 智能体发布 时序数据库 TDengine 3.3.6 发布会即将开启

从海量监控数据&#xff0c;到工业、能源、交通等场景中实时更新的各类传感器数据&#xff0c;时序数据正在以指数级速度增长。而面对如此庞杂的数据&#xff0c;如何快速分析、自动发现问题、精准预测未来&#xff0c;成为企业数字化转型过程中的关键挑战。 TDengine 的答案是…

vscode 通过Remote-ssh远程连接服务器报错 could not establish connection to ubuntu

vscode 通过Remote-ssh插件远程连接服务器报错 could not establish connection to ubuntu&#xff0c;并且出现下面的错误打印&#xff1a; [21:00:57.307] Log Level: 2 [21:00:57.350] SSH Resolver called for "ssh-remoteubuntu", attempt 1 [21:00:57.359] r…

【JavaScript 简明入门教程】为了Screeps服务的纯JS入门教程

0 前言 0-1 Screeps: World 众所不周知&#xff0c;​Screeps: World是一款面向编程爱好者的开源大型多人在线即时战略&#xff08;MMORTS&#xff09;沙盒游戏&#xff0c;其核心机制是通过编写JavaScript代码来控制游戏中的单位&#xff08;称为“Creep”&#xff09;&#…