庄懂的TA笔记(十四十六)<特效:火焰 + 水流>

庄懂的TA笔记(十四&十六)<特效:火焰 + 水流>

目录

一、作业展示:

二、示范:火:

        参考资料:

        实现思路:

        实践操作:

三、示范:水:

        实现思路:

        实践操作:


正文:

一、作业展示:

二、示范:火

(内焰 + 外焰)

参考资料:

1、火焰参考视频:

2、博客推荐:Simon schreibt.

实现思路:

1、通道使用

红:代表 火的 外 焰

绿:代表 火的 内 焰

蓝:剩余其他部分

2、噪波和形状结合

分别对 红R 绿G 两个通道 相乘* Noise 噪波图,做UV 流动Tilling

3、Noise 噪波图:

这里因为用到了两张noise噪波图,所以,分别将 两个灰度噪波图 放在 R通道,和G通道中。

这样,两张噪波混合,通过流速,和方向的修改,可以带来更多的随机性

4、实现下图右下角扰动效果

噪波1 + 噪波2 * a指形遮罩 * 渐变遮罩 = 随即流动 的 指型噪波

这里是 = 黑不透 白透.

他想要火焰下面的部分扰动少一些,所以下面黑色多一些。

他想要火焰集中在本身,所以在中间多一些白色

5、将UV和上面的遮罩相加,只用到了 V,就是Y轴,向上滚动 。

得到的结果就如下图,右下角效果。

Resulut(结果) = UV + R噪波 + G噪波 * A-1透贴 * A-2透贴

然后这里的Result 就可以 添加 自定义色彩,

绿色部分(内焰)给他一个什么颜色,

红色部分(外焰)给他一个什么颜色,

蓝色 或 A 部分 (透贴),把他们掏干净,这个事情就结束了。

如下图

实践操作:

引用AB模板开始Code代码.

1、声明出贴图和 对应 的 控制 参数:

_Mask(“R: 外焰 G:内焰 B:透贴 ”,2d )=“blue”{}

_Noise (“R: 噪波1 , G:噪波2 ”,2d)="gray"{}

对应控制参数:控制 两张噪波图的 Tilling大小流速扭曲强度 .

_Noise1Parms ("X: 大小 Y: 流速 Z: 强度 W: 无 " , vector) = (1,0.2,0.2,1)

_Noise2Parms ("X: 大小 Y: 流速 Z: 强度 W: 无 " , vector) = (1,0.2,0.2,1)

2、输出结构中定义输出3个UV,对3个UV进行控制。

UV1 采样 到 Mask

UV2 采样 到 Noise1

UV3 采样 到 Noise2

3、在 顶点shader中 将上述3个UV对应上.

o.uv0 = v.uv0;

注意:因为之前加Tilling是直接加 _ST进行控制的,但是这里,我们把两个噪波图放到了一个贴图中,如果按照_ST写,那么会让两个噪波图按照一个Tillng进行参数变换,所以这里需要我们 把他们分开来写。

重温:_ST的Tilingoffset 原理是什么 ?

** UV 乘以_ST的 XY 分量,+ ZW 分量 = 实现Tiling offset .

这里我们用的图 都是 四方连续的,所以,这里可以用一个 float 来进行 Tiling (XY)的控制,也就是XY的分量都等于一个值,做等比放缩

那么我们就可以将 已声明的_Noise1Parms 中的X分量和 o.uv1 相乘即可。

(这里噪波1 和噪波2 同理)

o.uv1 = v.uv * _Noise1Parms . x ;

o.uv2 = v.uv * _Noise2Parms . x ;


3.1、让 噪波1 和噪波2 流动起来

通过 + 取余和Time.x,并用_Noise1-2Parms中Y分量 相乘 控制(流速).

o.uv1 = v.uv * _Noise1Parms . x + frac(_Time.x * _Noise1Parms.y) ;

o.uv2 = v.uv * _Noise2Parms . x  + frac(_Time.x * _Noise2Parms.y) ;  


3.2、修正斜上流动方式;

修正:我们需要的是向上流动,而不是 斜上流动,这里发生这种情况的 原因是因为,

我们用一个一维向量(float)加到了一个 二维向量UV(float2)当中了float1同时给float2的两个参数相加所以出现了斜上的状态

解决方法:我们自己 构造 一个 二维向量,给他 加上去==其实就是float2 (0,流动).

o.uv1 = v.uv * _Noise1Parms . x + float2( 0.0, frac(_Time.x * _Noise1Parms.y)) ;

o.uv2 = v.uv * _Noise2Parms . x + float2( 0.0, frac(_Time.x * _Noise2Parms.y)) ;

这样就可以使UV在一个轴向上运动了。

上下,可以通过 更改 + - 来修改流向.

4、在像素shader中采样 和计算:

float var_Noise1 = tex2D(_Noise,i.uv1).r; (采样噪波图1,在R通道中)。

float var_Noise1 = tex2D(_Noise,i.uv1).g; (采样噪波图2,在G通道中)。


4.2、在像素shader中 开始混合 两个 Noise ,并控制强度:

//混合噪波图 = 噪波1 * Noise1Parms的Z分量(强度) + 噪波2 * Noise2Parms的Z分量(强度).

float noise = var_Noise1 * _Noise1Parms.z + var_Noise2 * _Noise2Parms.z;


4.3、在像素shader中 开始 构造 扰动 到 Mask 图:

像素shader中声明一个二维UV向量, 为扰动 Mask做准备,这里只需把i.uv0 + noise(流动扰动).

//声明一个WarpUV,用noise 来 扰动Mask的uv.

float2 warpUV = i.uv0 + noise;

(这里注意,i.uv0是二维的,noise是一维的,需要更正为构造为二维向量)。

float warpMask = tex2D(_Mask, i.uv0).b;(采样B通道渐变)

* warpMask 是为遮罩 扭曲UV 的强度

float2 warpUV = i.uv0 + float2(0,noise) * warpMask;

(这里可以看下UV长什么样子)

return float4 (i.uv0,0,1);

(这里在看下UV扰动之后的样子)

return float4(warpUV,0,1);

4.4、用扰动后的UV(WarpUV)采样Mask贴图。

float3 var_Mask = tex2D(_Mask,warpUV);

return float4 (finalRGB , 1);

4.5、添加自定义色彩 + 扣除透明:

外焰的Color * 外焰的Mask + 内焰的Color * 内焰的Mask = finalRGB

float3 finalRGB = _Color1 * var_Mask.r + _Color2 * var_Mask.g;

//扣除透明通道 红通道区域的空白 + 蓝通道区域的空白 = 黑的数值扣除。

因为retrun本身的 A 通道 就相当于 (1-输入进去的区域数值)黑的数值区域扣掉,白的数值区域保留。

float opacity = var_Mask.r + var_Mask.g;

return float4(finalRGB,opacity);

代码模板:

Shader "AP01/L16/Fire" {
    Properties {
        _Mask           ("R:外焰 G:内焰 B:透贴", 2d) = "blue"{}
        _Noise          ("R:噪声1 G:噪声2", 2d) = "gray"{}
        _Noise1Params   ("噪声1 X:大小 Y:流速 Z:强度", vector) = (1.0, 0.2, 0.2, 1.0)
        _Noise2Params   ("噪声2 X:大小 Y:流速 Z:强度", vector) = (1.0, 0.2, 0.2, 1.0)

        [HDR]_Color1    ("外焰颜色", color) = (1,1,1,1)
        [HDR]_Color2    ("内焰颜色", color) = (1,1,1,1)
    }
    SubShader {
        Tags {
            "Queue"="Transparent"               // 调整渲染顺序
            "RenderType"="Transparent"          // 对应改为Cutout
            "ForceNoShadowCasting"="True"       // 关闭阴影投射
            "IgnoreProjector"="True"            // 不响应投射器
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
            Blend One OneMinusSrcAlpha          // 修改混合方式One/SrcAlpha OneMinusSrcAlpha
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma target 3.0
            // 输入参数
            uniform sampler2D _Mask;    uniform float4 _Mask_ST;
            uniform sampler2D _Noise;
            uniform half3 _Noise1Params;
            uniform half3 _Noise2Params;
            uniform half3 _Color1;
            uniform half3 _Color2;
            // 输入结构
            struct VertexInput {
                float4 vertex : POSITION;       // 顶点位置 总是必要
                float2 uv : TEXCOORD0;          // UV信息 采样贴图用
            };
            // 输出结构
            struct VertexOutput {
                float4 pos : SV_POSITION;       // 顶点位置 总是必要
                float2 uv0 : TEXCOORD0;         // UV信息 采样Mask
                float2 uv1 : TEXCOORD1;         // UV信息 采样Noise1
                float2 uv2 : TEXCOORD2;         // UV信息 采样Noise2
            };
            // 输入结构>>>顶点Shader>>>输出结构
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                    o.pos = UnityObjectToClipPos( v.vertex);    // 顶点位置 OS>CS
                    o.uv0 = TRANSFORM_TEX(v.uv, _Mask);
                    o.uv1 = o.uv0 * _Noise1Params.x - float2(0.0, frac(_Time.x * _Noise1Params.y));
                    o.uv2 = o.uv0 * _Noise2Params.x - float2(0.0, frac(_Time.x * _Noise2Params.y));
                return o;
            }
            // 输出结构>>>像素
            half4 frag(VertexOutput i) : COLOR {
                // 扰动遮罩
                half warpMask = tex2D(_Mask, i.uv0).b;
                // 噪声1
                half var_Noise1 = tex2D(_Noise, i.uv1).r;
                // 噪声2
                half var_Noise2 = tex2D(_Noise, i.uv2).g;
                // 噪声混合
                half noise = var_Noise1 * _Noise1Params.z + var_Noise2 * _Noise2Params.z;
                // 扰动UV
                float2 warpUV = i.uv0 - float2(0.0, noise) * warpMask;
                // 采样Mask
                half3 var_Mask = tex2D(_Mask, warpUV);
                // 计算FinalRGB 不透明度
                half3 finalRGB = _Color1 * var_Mask.r + _Color2 * var_Mask.g;
                half opacity = var_Mask.r + var_Mask.g;
                return half4(finalRGB, opacity);                // 返回值
            }
            ENDCG
        }
    }
}

三、示范:水

实现思路:

1、水效果实现思路:

一个RampTex扰动贴图 ,用

不同Tiling大小值 ,

不同流向

不同速度

不同强度

来实现水面的 扰动,叠加。

2、总结参数:

baseTex 基础贴图

RampTex扰动贴图:

noise01 X:Tiling大小 Y:流向 Z:速度 W:强度

noise02 X:Tiling大小 Y:流向 Z:速度 W:强度

实践操作:

1、水卡通贴图MainTex 噪波贴图WarpTex 其他控制参数

_MainTex ("颜色贴图", 2d) = "white"{}//主水面卡通贴图

_Speed ("X:流速X Y:流速Y", vector) = (1.0, 1.0, 0.5, 1.0) //控制主图流动速度

_WarpTex ("扰动图", 2d) = "gray"{} //噪波图

//噪波1的控制参数

_Warp1Params ("X:大小 Y:流速X Z:流速Y W:强度", vector) = (1.0, 1.0, 0.5, 1.0)

//噪波2的控制参数

_Warp2Params ("X:大小 Y:流速X Z:流速Y W:强度", vector) = (2.0, 0.5, 0.5, 1.0)

2、顶点结构中 为 MainTex 和 WarpTex 增加 对应UV控制

MainTex占用1个UV。

WarpTex占用2个UV。

o.uv0 = TRANSFORM_TEX(v.uv, _MainTex) - frac(_Time.x * _Speed);

这里因为水面是需要 U 和 V两个方向都流动,就不能沿用上个火的案例来构造偏移量了。

那么两个轴 都需要 我们怎么写呢?

UV分量分别是 YZ的流速。

o.uv1 = v.uv * _Warp1Params.x - frac(_Time.x * _Warp1Params.yz);

o.uv2 = v.uv * _Warp2Params.x - frac(_Time.x * _Warp2Params.yz);

3、像素shader中,采样 Warp贴图和MainTex贴图:

采样Warp贴图和MainTex贴图:

half3 var_Warp1 = tex2D(_WarpTex, i.uv1).rgb; // 扰动1

half3 var_Warp2 = tex2D(_WarpTex, i.uv2).rgb; // 扰动2

混合两个扰动强度

half2 warp = (var_Warp1.yz - 0.5) * _Warp1Params.w +

                      (var_Warp2.yz - 0.5) * _Warp2Params.w;

UV扰动相加:

float2 warpUV = i.uv0 + warp;

采样MainTex 并输出:

half4 var_MainTex = tex2D(_MainTex, warpUV);

return float4(var_MainTex.xyz, 1.0);

代码示例:

Shader "AP01/L16/Water" {
    Properties {
        _MainTex        ("颜色贴图", 2d) = "white"{}
        _WarpTex        ("扰动图", 2d) = "gray"{}
        _Speed          ("X:流速X Y:流速Y", vector) = (1.0, 1.0, 0.5, 1.0)
        _Warp1Params    ("X:大小 Y:流速X Z:流速Y W:强度", vector) = (1.0, 1.0, 0.5, 1.0)
        _Warp2Params    ("X:大小 Y:流速X Z:流速Y W:强度", vector) = (2.0, 0.5, 0.5, 1.0)
    }
    SubShader {
        Tags {
            "RenderType"="Opaque"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }


            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma target 3.0
            // 输入参数
            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
            uniform sampler2D _WarpTex;
            uniform half2 _Speed;
            uniform half4 _Warp1Params;
            uniform half4 _Warp2Params;
            // 输入结构
            struct VertexInput {
                float4 vertex : POSITION;       // 顶点位置 总是必要
                float2 uv : TEXCOORD0;          // UV信息 采样贴图用
            };
            // 输出结构
            struct VertexOutput {
                float4 pos : SV_POSITION;       // 顶点位置 总是必要
                float2 uv0 : TEXCOORD0;         // UV信息 采样Mask
                float2 uv1 : TEXCOORD1;         // UV信息 采样Noise1
                float2 uv2 : TEXCOORD2;         // UV信息 采样Noise2
            };
            // 输入结构>>>顶点Shader>>>输出结构
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                    o.pos = UnityObjectToClipPos( v.vertex);    // 顶点位置 OS>CS
                    o.uv0 = v.uv - frac(_Time.x * _Speed);
                    o.uv1 = v.uv * _Warp1Params.x - frac(_Time.x * _Warp1Params.yz);
                    o.uv2 = v.uv * _Warp2Params.x - frac(_Time.x * _Warp2Params.yz);
                return o;
            }
            // 输出结构>>>像素
            float4 frag(VertexOutput i) : COLOR {
                half3 var_Warp1 = tex2D(_WarpTex, i.uv1).rgb;      // 扰动1
                half3 var_Warp2 = tex2D(_WarpTex, i.uv2).rgb;      // 扰动2
                // 扰动混合
                half2 warp = (var_Warp1.xy - 0.5) * _Warp1Params.w +
                             (var_Warp2.xy - 0.5) * _Warp2Params.w;
                // 扰动UV
                float2 warpUV = i.uv0 + warp;
                // 采样MainTex
                half4 var_MainTex = tex2D(_MainTex, warpUV);

                return float4(var_MainTex.xyz, 1.0);
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

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

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

相关文章

PCB 布线技术~PCB结构:Traces,电源平面

PCB导体:Traces • 铜是PCB中最常用的导体 – 走线或连接器一般通过镀金来提供一个抗腐蚀的电传导特性 – 走线的宽度和长度-由PCB布线工程师控制 • 在通常的制造工艺下,走线的宽度和之间的间距一般要≥5 mil – 走线厚度-制造工艺的变量 • 典型值 0.5oz – 3oz •…

C++(2):变量和基本类型

基本内置类型 C定义了一套包括算术类型(arithmetic type)和空类型(void)在内的基本数据类型。其中算术类型包含了字符、整型数、布尔值和浮点数。空类型不对应具体的值。 算数类型 算数类型分为两类:整型&#xff0…

【Linux】多种环境变量介绍与设置

文章目录 一. linux环境变量介绍1. linux中的环境变量配置文件2. 环境变量加载顺序 二. 操作环境变量1. 读取环境变量envexportecho $PATH 2. 设置环境变量2.1. export PATH:临时的环境变量2.2. 用户的环境变量vim ~/.bashrcvim ~/.bash_profile 2.3. 所有用户的环境…

网络原理(四):传输层协议 TCP/UDP

目录 应用层 传输层 udp 协议 端口号 报文长度(udp 长度) 校验和 TCP 协议 确认应答 超时重传 链接管理 滑动窗口 流量控制 拥塞控制 延时应答 捎带应答 总结 我们第一章让我们对网络有了一个初步认识,第二章和第三章我们通…

SpringBoot 整合 ChatGPT API 项目实战

SpringBoot 整合 ChatGPT API 项目实战 一、准备工作 二、补全接口示例 三、申请API-KEY 四、JavaScript调用API 五、SpringBoot使用ChatGPT API 体验到了ChatGPT的强大之后,那么我们会想,如果我们想基于ChatGPT开发一个自己的聊天机器人&#xff0…

论文、专利、文献检索及图像数据工具总结

一、文献检索 1、中文文献检索参考 中文文献途径网址用途1知网https://www.cnki.net/文献检索、下载2万方数据网https://www.wanfangdata.com.cn/文献检索、下载3维普期刊http://lib.cqvip.com/文献检索、下载4浙江图书馆https://www.zjlib.cn/#searchs_1_div文献检索、下载5…

html监听界面被隐藏或显示

vue相比于小程序和uni-app 显然少了两个有点用的生命周期 onShow 应用被展示 onHide 应用被隐藏 但其实这个 要做其实也很简单 JavaScript中 有对应的visibilitychange事件可以监听 我们Html参考代码如下 <!DOCTYPE html> <html lang"en"> <head>…

8. 机器学习系统设计

假设你想建立一个垃圾邮件分类器&#xff0c;通过监督学习来构造一个分类器来区分垃圾邮件和非垃圾邮件。为了应用监督学习&#xff0c;首先要想的就是&#xff1a;如何来表示邮件的特征向量x&#xff0c;通过特征向量x和分类标签y&#xff0c;我们就能训练一个分类器&#xff…

07-通过RocketMQ和Redis实现用户动态提醒

1、用户动态表 CREATE TABLE `t_user_moments` (`id` bigint(12) unsigned NOT NULL AUTO_INCREMENT COMMENT 主键id,`user_id` bigint(12) DEFAULT NULL COMMENT 用户id,`user_type` int(8) DEFAULT NULL COMMENT 动态类型:0视频 1直播 2专栏动态,`contend_id` bigint(12) D…

Linux下C/C++实现DNS查询(DNS QUERY)

DNS 的全称是 Domain Name System 或者 Domain Name Service&#xff0c;它主要的作用就是将人们所熟悉的网址 (域名) “翻译”成电脑可以理解的 IP 地址&#xff0c;这个过程叫做 DNS 域名解析。域名是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称&am…

从裸机启动开始运行一个C++程序(二)

先序文章请看&#xff1a; 从裸机启动开始运行一个C程序&#xff08;一&#xff09; 运行在8086上的第一个程序 既然硬件环境已经就绪了&#xff0c;那接下来&#xff0c;就要想办法让它运行我们的程序了。不过在此之前&#xff0c;我们必须要了解一下8086的主要架构&#xf…

微星MSI GE66 10SF-416RU电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网&#xff0c;转载需注明出处。&#xff08;下载请直接百度黑果魏叔&#xff09; 硬件配置 硬件型号驱动情况 主板Intel HM470 处理器Intel Core i7-10875H 2.30GHz up to 5.10GHz已驱动 内存Kingston Fury Impact DDR4 2x16Gb 3200mhz已驱动 硬盘NT…

【Linux】权限的理解

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

Apache Flink 文件上传漏洞 (CVE-2020-17518)

文章目录 一、Apache Flink简介二、漏洞简介三、漏洞复现四、上传jar包getshell 一、Apache Flink简介 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行&#xff0c;并能以内存速度和任…

自定义组件3-behaviors

1、behaviors是小程序中用于实现组件间代码共享的特性&#xff0c;类似于Vue.js中的mixins 2、behaviors的工作方式 每个behaviors可以包含一组属性、数据、生命周期函数和方法。组件引用它时&#xff0c;它的数据和属性和方法会被 合并到组件中。 每个组件可以引用多个behav…

NXP MCUXPresso - cc1plus.exe: out of memory allocating 65536 bytes

文章目录 NXP MCUXPresso - cc1plus.exe: out of memory allocating 65536 bytes概述实验结论补充END NXP MCUXPresso - cc1plus.exe: out of memory allocating 65536 bytes 概述 在尝试迁移 openpnp - Smoothieware project 从gcc命令行 MRI调试方式 到NXP MCUXpresso工程…

数据库界的科技与狠活: 创邻科技Galaxybase X英特尔SGX数据加密解决方案正式发布

引言 近日&#xff0c;创邻科技入选与英特尔合作&#xff0c;在基于第四代英特尔至强处理器的支持下&#xff0c;利用软件防护扩展&#xff08;Software Guard Extension,SGX&#xff09; 技术&#xff0c;打造出了具备可信执行环境的图数据库产品&#xff0c;保护企业释放关联…

nodejs进阶(4)—读取图片到页面

我们先实现从指定路径读取图片然后输出到页面的功能。 先准备一张图片imgs/dog.jpg。 file.js里面继续添加readImg方法&#xff0c;在这里注意读写的时候都需要声明binary。&#xff08;file.js 在上一篇文章nodejs进阶3-路由处理中有完整的内容&#xff09; readImg:functi…

03)FastDFS配置nginx 服务,使用http方式访问图片

FastDFS是没有文件访问功能的,需要借助其他工具实现图片HTTP访问的。 没安装nginx时比如前端html网页想获取 FastDFS的一张图片显示,需要java写个controller,然后使用 FastDFS-java client客户端调用文件获取api,HttpServletResponre在返回图片流.给前端显示。 安装了nginx…

计算机图形学-GAMES101-9

前言 材质和光的相互作用很重要。VertexShader和FragmentShader。纹理贴图Texture mapping。 一、在三角形中插值 为什么要在三角形内部插值&#xff1f;虽然我们的操作很多是在三角形顶点上进行计算的&#xff0c;但是对于三角形内部我们也希望每个像素点能得到一个值&…