消融效果

消融效果是模拟物体逐渐从屏幕上消失或溶解的过程,它通常利用噪声纹理实现,使物体按照某种规则逐渐透明或完全不可见。这种效果常用于: 角色死亡、传送场景、 魔法消失,比如燃烧、消失等

1、基本原理

通过对比噪声纹理值与消融进度参数,剔除低于阈值的像素,同时在边缘添加渐变颜色实现动态溶解效果。
关键点:

  • 如何剔除像素

在片元着色器中对噪声纹理进行采样,由于噪声纹理是灰度图,只需取出其中的RGB中的任意一通道的颜色来使用。再自定义一个用于控制消融进度的参数(0~1),最后利用该片元的 噪声纹理值 – 进度参数,若小于0则不渲染该片元,通过控制进度参数,便可以控制消融程度了

  • 如何处理边缘

在处理边缘渐变颜色效果时,将使用Unity中内置的三个Shader函数:


smoothstep(a, b, x)

a起始值;b结束值;x输入值(用于在a和b之间平滑插值)
当x<a时,返回0;当x>b时,返回1;
a < x < b时,返回0~1之间的值


lerp(a,b,t)
a起始值;b结束值;t插值因子
当t=0时,返回a;当t=1时,返回b;当 0 < t < 1时;返回a和b之间的值


step(value, x)
value阈值,x输入值;两值用于比较
x < value,返回0;x>=value,返回1


首先我们利用smoothstep函数决定边缘颜色,利用噪声颜色值 – 消融进度值 得到一个剔除阈值value,然后自定义一个边缘范围值_Range,然后用smoothstep函数来得到一个值

接着在原本的颜色和渐变颜色之间进行插值,决定使用哪个颜色。

利用smoothstep结合消融阈值来决定在渐变纹理中采用的渐变颜色,利用lerp来决定在原始颜色和边缘渐变颜色中使用哪个颜色,用自定义参数来决定边缘范围,从而实现消融边缘渐变色

2、实现

Shader "ShaderProj/21/Dissolve"
{
    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _MainColor ("MainColor", Color) = (1,1,1,1)
        _BumpMap("BumpMap", 2D) = ""{}
        _BumpScale("BumpScale", Range(0, 1)) = 1
        _SpecularColor("SpecularColor", Color) = (1,1,1,1)
        _SpecularNum("SpecularNum", Range(8, 256)) = 18

        _Noise ("Noise", 2D) = ""{}
        _Gradient ("Gradient", 2D) = ""{}
        _Dissolve ("Dissolve", Range(0, 1)) = 0
        _EdgeRange ("EdgeRange", Range(0, 1)) = 0
    }
    SubShader
    {
        Pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fwdbase
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            struct v2f
            {
                float4 uv : TEXCOORD0;
                float4 pos : SV_POSITION;
                float3 lightDir : TEXCOORD1;
                float3 viewDir : TEXCOORD2;
                float2 uvNoise : TEXCOORD3;
                float3 worldPos : TEXCOORD4;
                SHADOW_COORDS(5)
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _MainColor;
            sampler2D _BumpMap;
            float4 _BumpMap_ST;
            float _BumpScale;
            fixed4 _SpecularColor;
            fixed _SpecularNum;
            sampler2D _Noise;
            float4 _Noise_ST;
            sampler2D _Gradient;
            fixed _Dissolve;
            fixed _EdgeRange;

            v2f vert (appdata_full v)
            {
                v2f data;
                data.pos = UnityObjectToClipPos(v.vertex);
                data.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
                data.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);
                data.uvNoise = TRANSFORM_TEX(v.texcoord, _Noise);

                float3 binormal = cross(normalize(v.tangent), normalize(v.normal)) * v.tangent.w;
                float3x3 rotation = float3x3(v.tangent.xyz,
                                             binormal,
                                             v.normal);
                data.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));
                data.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex));
                data.worldPos = mul(unity_ObjectToWorld, v.vertex);

                TRANSFER_SHADOW(data);
                return data;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // 剔除
                fixed3 noiseColor = tex2D(_Noise, i.uvNoise);
                clip(_Dissolve == 1 ? -1 : noiseColor - _Dissolve);

                float4 packedNormal = tex2D(_BumpMap, i.uv.zw);
                float3 tangentNormal = UnpackNormal(packedNormal);
                tangentNormal.xy *= _BumpScale;
                tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));

                fixed3 albedo = tex2D(_MainTex, i.uv.xy) * _MainColor.rgb;
                fixed3 lambertColor = _LightColor0.rgb * albedo.rgb * max(0, dot(tangentNormal, normalize(i.lightDir)));
                float3 halfA = normalize(normalize(i.viewDir) + normalize(i.lightDir));
                fixed3 specularColor = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(tangentNormal, normalize(i.viewDir))), _SpecularNum);

                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

                fixed3 color = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo + lambertColor * atten + specularColor;

                // 渐变颜色
                fixed t = 1 - smoothstep(0, _EdgeRange, noiseColor - _Dissolve);
                fixed3 gradient = tex2D(_Gradient, fixed2(t, 0));
                fixed3 finalColor = lerp(color, gradient, t * step(0.00001, _Dissolve));

                return fixed4(finalColor, 1);
            }
            ENDCG
        }
        Pass{
            Tags{"LightMode" = "ShadowCaster"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_shadowcaster
            #include "UnityCG.cginc"

            struct v2f
            {
                V2F_SHADOW_CASTER;
                fixed2 uvNoise : TEXCOORD0;
            };

            sampler2D _Noise;
            float4 _Noise_ST;
            float _Dissolve;

            v2f vert(appdata_base v)
            {
                v2f data;
                data.uvNoise = TRANSFORM_TEX(v.texcoord, _Noise); 
                TRANSFER_SHADOW_CASTER_NORMALOFFSET(data);
                return data;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                // 剔除影子
                fixed3 noiseColor = tex2D(_Noise, i.uvNoise);
                clip(_Dissolve == 1 ? -1 : noiseColor - _Dissolve);
                SHADOW_CASTER_FRAGMENT(i);
            }

            ENDCG
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java后端之事务管理

Transactional注解&#xff1a;作用于业务层的方法、类、接口上&#xff0c;将当前方法交给spring进行事务管理&#xff0c;执行前开启事务&#xff0c;成功执行则提交事务&#xff0c;执行异常回滚事务 spring事务管理日志&#xff1a; 默认情况下&#xff0c;只有出现Runti…

【Paper Tips】随记2-word版快速删除某字符

写paper时随心记录一些对自己有用的skills与tips。 文章目录 一、待解决问题1.1 问题描述1.2 解决方法 二、方法详述2.1 必要说明2.2 应用步骤2.2.1 CtrlH一键全文替换2.2.2 录制宏 三、疑问四、总结 一、待解决问题 1.1 问题描述 word中粘贴部分文字时&#xff0c;格式不对时…

vite环境变量处理

环境变量: 会根据当前代码环境产生值的变化的变量就叫做环境变量 代码环境: 开发环境测试环境预发布环境灰度环境生产环境 举例: 百度地图 SDK,小程序的SDK APP_KEY: 测试环境和生产环境还有开发环境是不一样的key 开发环境: 110 生产环境:111 测试环境: 112 我们去请求第三…

使用JavaScript实现猜数字小功能

引言&#xff1a; 在学习编程的过程中&#xff0c;通过实际的小项目来巩固知识是非常有效的方法。今天&#xff0c;我们将使用 JavaScript 来实现一个简单的猜数字游戏。这个游戏不仅能让我们熟悉 JavaScript 的基本语法&#xff0c;还能锻炼我们的逻辑思维能力。 游戏规则 …

数据结构——概念与时间空间复杂度

目录 前言 一相关概念 1什么是数据结构 2什么是算法 二算法效率 1如何衡量算法效率的好坏 2算法的复杂度 三时间复杂度 1时间复杂度表示 2计算时间复杂度 2.1题一 2.2题二 2.3题三 2.4题四 2.5题五 2.6题六 2.7题七 2.8题八 四空间复杂度 1题一 2题二 3…

【转帖】eclipse-24-09版本后,怎么还原原来版本的搜索功能

【1】原贴地址&#xff1a;eclipse - 怎么还原原来版本的搜索功能_eclipse打开类型搜索类功能失效-CSDN博客 https://blog.csdn.net/sinat_32238399/article/details/145113105 【2】原文如下&#xff1a; 更新eclipse-24-09版本后之后&#xff0c;新的搜索功能&#xff08;CT…

Django基础之ORM

一.前言 上一节简单的讲了一下orm&#xff0c;主要还是做个了解&#xff0c;这一节将和大家介绍更加细致的orm&#xff0c;以及他们的用法&#xff0c;到最后再和大家说一下cookie和session&#xff0c;就结束了全部的django基础部分 二.orm的基本操作 1.settings.py&#x…

单片机-STM32 IIC通信(OLED屏幕)(十一)

一、屏幕的分类 1、LED屏幕&#xff1a; 由无数个发光的LED灯珠按照一定的顺序排列而成&#xff0c;当需要显示内容的时候&#xff0c;点亮相关的LED灯即可&#xff0c;市场占有率很高&#xff0c;主要是用于户外&#xff0c;广告屏幕&#xff0c;成本低。 LED屏是一种用发光…

纯css实现div宽度可调整

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>纯css实现div尺寸可调整</title><style…

国产编辑器EverEdit - 输出窗口

1 输出窗口 1.1 应用场景 输出窗口可以显示用户执行某些操作的结果&#xff0c;主要包括&#xff1a; 查找类&#xff1a;查找全部&#xff0c;筛选等待操作&#xff0c;可以把查找结果打印到输出窗口中&#xff1b; 程序类&#xff1a;在执行外部程序时(如&#xff1a;命令窗…

小游戏源码开发搭建技术栈和服务器配置流程

近些年各种场景小游戏开发搭建版本层出不穷,山东布谷科技拥有多年海内外小游戏源码开发经验&#xff0c;现为从事小游戏源码开发或游戏运营的朋友们详细介绍小游戏开发及服务器配置流程。 一、可以对接到app的小游戏是如何开发的 1、小游戏源码开发的需求分析&#xff1a; 明…

Linux C\C++编程-文件位置指针与读写文件数据块

【图书推荐】《Linux C与C一线开发实践&#xff08;第2版&#xff09;》_linux c与c一线开发实践pdf-CSDN博客 《Linux C与C一线开发实践&#xff08;第2版&#xff09;&#xff08;Linux技术丛书&#xff09;》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 Linu…

一文简单回顾复习Java基础概念

还是和往常一样&#xff0c;我以提问的方式回顾复习&#xff0c;今天回顾下Java小白入门应该知道的一些基础知识 Java语言有哪些特点呢&#xff1f; Java语言的特点有&#xff1a; 面向对象&#xff0c;主要是封装、继承、多态&#xff1b;平台无关性&#xff0c;“一次编写…

Redis实战(黑马点评)——关于缓存(缓存更新策略、缓存穿透、缓存雪崩、缓存击穿、Redis工具)

redis实现查询缓存的业务逻辑 service层实现 Overridepublic Result queryById(Long id) {String key CACHE_SHOP_KEY id;// 现查询redis内有没有数据String shopJson (String) redisTemplate.opsForValue().get(key);if(StrUtil.isNotBlank(shopJson)){ // 如果redis的数…

神经网络|(四)概率论基础知识-古典概型

【1】引言 前序学习了线性回归的基础知识&#xff0c;了解到最小二乘法可以做线性回归分析&#xff0c;但为何最小二乘法如此准确&#xff0c;这需要从概率论的角度给出依据。 因此从本文起&#xff0c;需要花一段时间来回顾概率论的基础知识。 【2】古典概型 古典概型是我…

【C++】特殊类设计、单例模式与类型转换

目录 一、设计一个类不能被拷贝 &#xff08;一&#xff09;C98 &#xff08;二&#xff09;C11 二、设计一个类只能在堆上创建对象 &#xff08;一&#xff09;将构造函数私有化&#xff0c;对外提供接口 &#xff08;二&#xff09;将析构函数私有化 三、设计一个类只…

微服务网关鉴权之sa-token

目录 前言 项目描述 使用技术 项目结构 要点 实现 前期准备 依赖准备 统一依赖版本 模块依赖 配置文件准备 登录准备 网关配置token解析拦截器 网关集成sa-token 配置sa-token接口鉴权 配置satoken权限、角色获取 通用模块配置用户拦截器 api模块配置feign…

16.好数python解法——2024年省赛蓝桥杯真题

问题描述 一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位…)上的数字是奇数,偶数位(十位、千位、十万位…)上的数字是偶数,我们就称之为“好数”。 给定一个正整数N,请计算从1到N一共有多少个好数。 输入格式 一个整数N。 输出格式 一个整数代表答案。 样例输入 1 …

2025年数学建模美赛 A题分析(2)楼梯使用频率数学模型

2025年数学建模美赛 A题分析&#xff08;1&#xff09;Testing Time: The Constant Wear On Stairs 2025年数学建模美赛 A题分析&#xff08;2&#xff09;楼梯磨损分析模型 2025年数学建模美赛 A题分析&#xff08;3&#xff09;楼梯使用方向偏好模型 2025年数学建模美赛 A题分…

Redis实战(黑马点评)——涉及session、redis存储验证码,双拦截器处理请求

项目整体介绍 数据库表介绍 基于session的短信验证码登录与注册 controller层 // 获取验证码PostMapping("code")public Result sendCode(RequestParam("phone") String phone, HttpSession session) {return userService.sendCode(phone, session);}// 获…