庄懂的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的Tiling 和 offset 原理是什么 ?
** 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两个方向都流动,就不能沿用上个火的案例来构造偏移量了。
那么两个轴 都需要 我们怎么写呢?
U和V分量分别是 Y和Z的流速。
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);//_Speed的默认XY参数控制移动方向
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 主图UV+流动2UV
float2 warpUV = i.uv0 + warp;
// 采样MainTex
half4 var_MainTex = tex2D(_MainTex, warpUV);
return float4(var_MainTex.xyz, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
扩展练习作业:血液,血管,汁液,流动效果:
效果展示:
后更新,增加主图影响
代码示例:
Shader "Unlit/Sc016_UVWarpT04"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
[HDR]_MainCol ("MainCol",color)=(0,0,0,0)
_MainSpeed("主图速度X:左右 Y:上下",vector)=(1,1,1,1)
_MaskTex("MaskTex:遮罩图 R: G: B:",2D)="blue"{}
_Noise12Tex("NoiseTex:噪波图1 R: G: B:",2D)="gray"{}
_Noise34Tex("NoiseTex:噪波图1 R: G: B:",2D)="gray"{}
_Noise1Pramas("杂质 X:大小 Y:速度 Z:强度 W:",vector)=(1,1,1,1)
_Noise2Pramas("血小板 X:大小 Y:速度 Z:强度 W:",vector)=(1,1,1,1)
_Noise3Pramas("扰动1 X:范围 Y:左右Z:上下 W:强度",vector)=(1,1,1,1)
_Noise4Pramas("扰动2 X:范围 Y:左右Z:上下 W:强度",vector)=(1,1,1,1)
[HDR]_Color1 ("质强度",color)=(1,1,1,1)
[HDR]_Color2 ("血小板",color)=(1,1,1,1)
[HDR]_Color3 ("管壁",color)=(1,1,1,1)
_XgInt("血管壁强度",Range(0,10))=1
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Cull off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
UNITY_INSTANCING_BUFFER_START( Props )
// UNITY_DEFINE_INSTANCED_PROP( float4, _Color)
UNITY_INSTANCING_BUFFER_END( Props )
uniform sampler2D _MainTex;uniform float4 _MainTex_ST;
uniform float4 _MainCol;
uniform sampler2D _MaskTex;uniform float4 _MaskTex_ST;
uniform float4 _MainSpeed;
uniform sampler2D _Noise12Tex;uniform float4 _Noise12Tex_ST;
uniform sampler2D _Noise34Tex;uniform float4 _Noise34Tex_ST;
uniform float4 _Noise1Pramas;
uniform float4 _Noise2Pramas;
uniform float4 _Noise3Pramas;
uniform float4 _Noise4Pramas;
uniform float4 _Color1;
uniform float4 _Color2;
uniform float4 _Color3;
uniform float _XgInt;
//输入结构
struct VertexInput
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0; //main
float2 uv1 : TEXCOORD1; //mask
float2 uv2 : TEXCOORD2; //noise
};
//顶点输出结构
struct VertexOutput
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float2 uv2 : TEXCOORD2;
//血液UV滚动
float2 uv3 : TEXCOORD3;
float2 uv4 : TEXCOORD4;
//流动UV滚动
float2 uv5 : TEXCOORD5;
float2 uv6 : TEXCOORD6;
};
//输出结构>>>顶点shader>>>输出结构
VertexOutput vert (VertexInput v)
{
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv,_MainTex)-frac(_Time.x*_MainSpeed);
o.uv1 = TRANSFORM_TEX(v.uv1,_MaskTex);
o.uv2 = TRANSFORM_TEX(v.uv2,_Noise12Tex);
//血液UV滚动
o.uv3 = v.uv2 * _Noise1Pramas.x - float2(0,frac(_Time.x*_Noise1Pramas.y));
o.uv4 = v.uv2 * _Noise2Pramas.x - float2(0,frac(_Time.x*_Noise2Pramas.y));
//流动UV滚动
o.uv5 = v.uv2 * _Noise3Pramas.x - frac(_Time.x*_Noise3Pramas.yz);
o.uv6 = v.uv2 * _Noise4Pramas.x - frac(_Time.x*_Noise4Pramas.yz);
return o ;
}
//色彩输出结构
float4 frag(VertexOutput i) : COLOR
{
//贴图采样
//float4 var_MainTex = tex2D(_MainTex,i.uv);
float4 var_MaskTex = tex2D(_MaskTex,i.uv1);
float4 var_NoiseTex = tex2D(_Noise12Tex,i.uv2);
//血液UV滚动
float var_Noise1 = tex2D(_Noise12Tex,i.uv3).r;
float var_Noise2 = tex2D(_Noise12Tex,i.uv4).g;
//流动UV滚动
float var_Noise3 = tex2D(_Noise34Tex,i.uv5);
float var_Noise4 = tex2D(_Noise34Tex,i.uv6);
float noise1_2 = _Noise1Pramas.z * var_Noise1 + _Noise2Pramas.z * var_Noise2;
float noise3_4 = _Noise3Pramas.w * var_Noise3 + _Noise4Pramas.w * var_Noise4;
//float noise = noise1_2+noise3_4;
//float noise1234 = _Noise1Pramas.z*var_Noise1+_Noise2Pramas.z*var_Noise2+_Noise3Pramas*var_Noise3+_Noise4Pramas*var_Noise4;
float2 warpUV00 = (i.uv + noise3_4);
float2 maskUV = i.uv1 - float2(0,noise1_2)*var_MaskTex.b;
float3 FireMask = tex2D(_MaskTex,maskUV);
float3 mainMask = tex2D(_MainTex,warpUV00+maskUV)*_MainCol*var_MaskTex.b;
//R = 质 G=血小板 B = 管壁
//float3 finalRGB = lerp(FireMask.g*_Color2,_Color1*FireMask.r,FireMask.b*_Color3);
float3 Noise1C = _Color1*var_Noise1;//质 -控制杂质强弱
float3 Noise2C = _Color2*(Noise1C+var_Noise2)+_Color2/(Noise1C+var_Noise2);//血小板 -控制色彩
float3 Noise3C = _Color3*var_MaskTex.b; //血管壁 -控制显示强度
//float3 finalRGB = var_MaskTex.b*_XgInt * max(Noise2C,Noise1C)+Noise3C;
//float3 finalRGB = var_MaskTex.b*_XgInt * max(Noise2C,Noise3C);
float3 finalRGB = mainMask+FireMask.b*_XgInt * max(Noise2C,Noise3C);
//float3 finalRGB = var_MaskTex.b*_XgInt * max(Noise3C,Noise1C) * Noise2C;
float opacity = var_NoiseTex.r+var_NoiseTex.g+var_NoiseTex.b;
clip(opacity-0.01);
//return var_Noise1;
//return var_MaskTex;
//return var_MaskTex.b;
//return noise;
//return float4(FireMask,1);//输出最终颜色
//return float4(warpUV00,0,opacity);//输出最终颜色
return float4(finalRGB,opacity);//输出最终颜色
return float4(maskUV,0,1);//输出最终颜色
}
ENDCG
}
}
}
扰动效果2
Shader "Unlit/Sc016_UVWarpT04"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
[HDR]_MainCol ("MainCol",color)=(0,0,0,0)
_MainSpeed("主图速度X:左右 Y:上下",vector)=(1,1,1,1)
_MaskTex("MaskTex:遮罩图 R: G: B:",2D)="blue"{}
_Noise12Tex("NoiseTex:噪波图1 R: G: B:",2D)="gray"{}
_Noise1Pramas("杂质 X:大小 Y:速度 Z:强度 W:",vector)=(1,1,1,1)
_Noise2Pramas("血小板 X:大小 Y:速度 Z:强度 W:",vector)=(1,1,1,1)
_WarpInt("扭曲强度",Range(0,1))=0.1
[HDR]_Color1 ("质强度",color)=(1,1,1,1)
[HDR]_Color2 ("血小板",color)=(1,1,1,1)
[HDR]_Color3 ("管壁",color)=(1,1,1,1)
_XgInt("血管壁强度",Range(0,10))=1
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Cull off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
UNITY_INSTANCING_BUFFER_START( Props )
// UNITY_DEFINE_INSTANCED_PROP( float4, _Color)
UNITY_INSTANCING_BUFFER_END( Props )
uniform sampler2D _MainTex;uniform float4 _MainTex_ST;
uniform float4 _MainCol;
uniform sampler2D _MaskTex;uniform float4 _MaskTex_ST;
uniform float4 _MainSpeed;
uniform sampler2D _Noise12Tex;uniform float4 _Noise12Tex_ST;
uniform float4 _Noise1Pramas;
uniform float4 _Noise2Pramas;
uniform float4 _Noise3Pramas;
uniform float4 _Noise4Pramas;
uniform float4 _Color1;
uniform float4 _Color2;
uniform float4 _Color3;
uniform float _XgInt;
uniform float _WarpInt;
//输入结构
struct VertexInput
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0; //main
float2 uv1 : TEXCOORD1; //mask
float2 uv2 : TEXCOORD2; //noise
};
//顶点输出结构
struct VertexOutput
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float2 uv2 : TEXCOORD2;
//血液UV滚动
float2 uv3 : TEXCOORD3;
float2 uv4 : TEXCOORD4;
//流动UV滚动
float2 warp_uv5 : TEXCOORD5;
};
//输出结构>>>顶点shader>>>输出结构
VertexOutput vert (VertexInput v)
{
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv,_MainTex)-frac(_Time.x*_MainSpeed);
o.uv1 = TRANSFORM_TEX(v.uv1,_MaskTex);
o.uv2 = TRANSFORM_TEX(v.uv2,_Noise12Tex);
//血液UV滚动
o.uv3 = v.uv2 * _Noise1Pramas.x - float2(0,frac(_Time.x*_Noise1Pramas.y));
o.uv4 = v.uv2 * _Noise2Pramas.x - float2(0,frac(_Time.x*_Noise2Pramas.y));
o.warp_uv5 = TRANSFORM_TEX(o.warp_uv5,_Noise12Tex);
o.warp_uv5.y = o.warp_uv5 + frac(_Time.x)*2;
return o ;
}
//色彩输出结构
float4 frag(VertexOutput i) : COLOR
{
//贴图采样
//float4 var_MainTex = tex2D(_MainTex,i.uv);
float4 var_MaskTex = tex2D(_MaskTex,i.uv1);
float4 var_NoiseTex = tex2D(_Noise12Tex,i.uv2);
float4 var_WarpTex = tex2D(_Noise12Tex,i.warp_uv5).g;
//扭曲uv
float2 warpUV = (var_NoiseTex - 0.5)*_WarpInt;
//血液UV滚动
float var_Noise1 = tex2D(_Noise12Tex,i.uv3+warpUV).r;
float var_Noise2 = tex2D(_Noise12Tex,i.uv4+warpUV).g;
float noise1_2 = _Noise1Pramas.z * var_Noise1 + _Noise2Pramas.z * var_Noise2;
//float noise = noise1_2+noise3_4;
//float noise1234 = _Noise1Pramas.z*var_Noise1+_Noise2Pramas.z*var_Noise2+_Noise3Pramas*var_Noise3+_Noise4Pramas*var_Noise4;
float2 warpUV00 = (i.uv);
float2 maskUV = i.uv1 - float2(0,noise1_2)*var_MaskTex.b;
float3 FireMask = tex2D(_MaskTex,maskUV);
float3 mainMask = tex2D(_MainTex,warpUV00+maskUV)*_MainCol*var_MaskTex.b;
//R = 质 G=血小板 B = 管壁
//float3 finalRGB = lerp(FireMask.g*_Color2,_Color1*FireMask.r,FireMask.b*_Color3);
float3 Noise1C = _Color1*var_Noise1;//质 -控制杂质强弱
float3 Noise2C = _Color2*(Noise1C+var_Noise2)+_Color2/(Noise1C+var_Noise2);//血小板 -控制色彩
float3 Noise3C = _Color3*var_MaskTex.b; //血管壁 -控制显示强度
//float3 finalRGB = var_MaskTex.b*_XgInt * max(Noise2C,Noise1C)+Noise3C;
//float3 finalRGB = var_MaskTex.b*_XgInt * max(Noise2C,Noise3C);
float3 finalRGB = mainMask+FireMask.b*_XgInt * max(Noise2C,Noise3C);
//float3 finalRGB = var_MaskTex.b*_XgInt * max(Noise3C,Noise1C) * Noise2C;
float opacity = var_NoiseTex.r+var_NoiseTex.g+var_NoiseTex.b;
clip(opacity-0.01);
//return var_Noise1;
//return var_MaskTex;
//return var_MaskTex.b;
//return noise;
//return float4(FireMask,1);//输出最终颜色
//return float4(warpUV00,0,opacity);//输出最终颜色
return float4(finalRGB,opacity);//输出最终颜色
return float4(maskUV,0,1);//输出最终颜色
}
ENDCG
}
}
}
一、正常血管流动效果参考效果:
1、https://www.douyin.com/video/7228889472883117312
2、3D视频演示:血液流动的样子_哔哩哔哩_bilibili
二、Maya实现血液流动,血管瓣膜 影响效果实现:
示例图:
原文链接:
www.tshipin.com 英文名:
Animating Blood Flow in Maya