蔬菜网站模板,在线音乐网站开发现状,服装设计学什么,优秀的网站建设策划书文章目录 前言一、我们在片元着色器中#xff0c;实现卡通火的大体框架1、使用 noise 和 _CUTOFF 判断作为显示火焰的区域2、_CUTOFF #xff1a; 用于裁剪噪波范围的三角形3、noise getNoise(uv, t); : 噪波函数 二、顺着大体框架依次解析具体实现的功能1、 uv.x * 4.0; : … 文章目录 前言一、我们在片元着色器中实现卡通火的大体框架1、使用 noise 和 _CUTOFF 判断作为显示火焰的区域2、_CUTOFF 用于裁剪噪波范围的三角形3、noise getNoise(uv, t); : 噪波函数 二、顺着大体框架依次解析具体实现的功能1、 uv.x * 4.0; : 使用 uv 在 x 轴上的值从(0,1)扩大到(0,4)2、noise getNoise(uv, t); : 噪波函数3、_CUTOFF 用于裁剪噪波范围的三角形4、卡通火形状部分5、卡通火颜色部分 前言
在上一篇文章中我们实现卡通火ShaderToy到ShaderLab的移植。在这篇文章中我们来解析一下其原理。
我们在分析时需要从整体到局部。 依次从输出结果倒着逐步分解这样对于复杂的效果就不会迷失目标。
Unity中实现ShaderToy卡通火移植篇 一、我们在片元着色器中实现卡通火的大体框架
在片元着色器中我们可以看出主要实现的几个功能 fixed4 frag(v2f_img i) : SV_Target{float2 uv i.uv;uv.x * 4.0;float t _Time.y * 3.0;float3 col 0;float noise getNoise(uv, t);//shape _CUTOFF to get higher further up the screen_CUTOFF uv.y;//and at horiz edges_CUTOFF pow(abs(uv.x * 0.5 - 1.), 1.0);//debugview _CUTOFF field//fragColor float4(float3(_CUTOFF),1.0); if (noise _CUTOFF){//blackcol 0;}else{//firefloat d pow(getDepth(noise), 0.7);float3 hsv float3(d * 0.17, 0.8 - d / 4., d 0.8);col hsv2rgb(hsv);}return float4(col, 1.0);}1、使用 noise 和 _CUTOFF 判断作为显示火焰的区域
if (noise _CUTOFF)
{//blackcol 0;
}
else
{//firefloat d pow(getDepth(noise), 0.7);float3 hsv float3(d * 0.17, 0.8 - d / 4., d 0.8);col hsv2rgb(hsv);
}black部分当在遮罩范围外时返回黑色 fire部分显示 火的形状 和 火的着色 hsv2rgb : 由 hsv 转化为 RGB 色 hsv : 色相、饱和度、亮度 d 使用pow调节色阶范围 getDepth(noise) 将黑白灰渐变色分离成几个色阶以表现卡通效果
2、_CUTOFF 用于裁剪噪波范围的三角形
可以看出这就是我们卡通火的大概轮廓 三角形两侧都是 1白色在比较时小于1的部分都显示黑色。
3、noise getNoise(uv, t); : 噪波函数 二、顺着大体框架依次解析具体实现的功能
fixed4 frag(v2f_img i) : SV_Target
{float2 uv i.uv;uv.x * 4.0;float t _Time.y * 3.0;float3 col 0;float noise getNoise(uv, t);//shape : 模拟出火焰大体形态三角形_CUTOFF uv.y;//and at horiz edges_CUTOFF pow(abs(uv.x * 0.5 - 1.), 1.0);if (noise _CUTOFF){//blackcol 0;}else{//fire//计算得到 火的轮廓float d pow(getDepth(noise), 0.7);//计算得到 色相、明度、饱和度loat3 hsv float3(d * 0.17, 0.8 - d / 4., d 0.8);//将 HSV 转化为 RGBcol hsv2rgb(hsv);}return float4(col, 1.0);
}
1、 uv.x * 4.0; : 使用 uv 在 x 轴上的值从(0,1)扩大到(0,4) 2、noise getNoise(uv, t); : 噪波函数
//获取整屏的噪波效果
float getNoise(float2 uv, float t)
{//given a uv coord and time - return a noise val in range 0 - 1//using ashima noise//add time to y position to make noise field move upwardsfloat TRAVEL_SPEED 1.5;//octave 1float SCALE 2.0;float noise snoise(float3(uv.x * SCALE, uv.y * SCALE - t * TRAVEL_SPEED, 0));//octave 2 - more detailSCALE 6.0;noise snoise(float3(uv.x * SCALE t, uv.y * SCALE, 0)) * 0.2;//move noise into 0 - 1 range noise (noise / 2. 0.5);return noise;
}使用 TRAVEL_SPEED 、 SCALE 和 t 作为噪波因子作为影响生成噪波的主要参数 TRAVEL_SPEED : 流速 SCALE 缩放 t 时间 snoise(float3(x,y,z)); : 噪波生成算法(这里使用了 ashima noise 算法) Perlin噪声与Simplex噪声笔记 这里引用一篇别人的笔记作为该噪音函数的讲解
第一次噪波效果 第二次噪波效果 两次噪波叠加效果 noise (noise / 2. 0.5);将噪波归一化0,1
3、_CUTOFF 用于裁剪噪波范围的三角形 _CUTOFF uv.y; uv.x * 0.5 - 1 值域范围改变0,4- (0,2) - (-1,-1) abs(uv.x * 0.5 - 1.); : 使值域变成对称的样子 (-1,-1) - (1,0)、(0,1) pow(abs(uv.x * 0.5 - 1.), 2.0)可以用指数函数来控制三角形状的边扭曲程度 uv.y pow(abs(uv.x * 0.5 - 1.), 1.0) 实现三角形状
4、卡通火形状部分
将黑白灰渐变色分离成几个色阶以表现卡通效果 //计算得到 火的轮廓 float d pow(getDepth(noise), 0.7); // 将黑白灰渐变色分离成几个色阶以表现卡通效果
float getDepth(float n)
{//given a 0-1 value return a depth,//remap remaining non-_CUTOFF region to 0 - 1//实现边缘虚化的作用把原本尖锐的边缘 变得虚化柔和float d (n - _CUTOFF) / (1. - _CUTOFF);return d;//色调分离d floor(d * _Steps) / _Steps;return d;
}n - _CUTOFF 的效果 float d (n - _CUTOFF) / (1. - _CUTOFF); 边缘虚化归一化后 色调分离 d floor(d * _Steps) / _Steps; 把上面计算的结果进行乘以一个较大的数使用向下取整后再除以这个较大的数归一化。以达到卡通效果中一块一块的色调效果 pow 用来调节亮度
5、卡通火颜色部分
hsv 是一种符合 人眼 对颜色感性认识 的特征值
计算得到 色相、饱和度、亮度。这里的特征值是 计算出符合 火的颜色区间范围。 其他效果的颜色需要自己调整寻找颜色算法 float3 hsv float3(d * 0.17, 0.8 - d / 4., d 0.8); rgb 是一种符合 计算机硬件设计 的 颜色设计。使用算法把 hsv 转化到 rgb float3 hsv2rgb(float3 c) { float4 K float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); float3 p abs(frac(c.xxx K.xyz) * 6.0 - K.www); return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } 这里给出taecg老师总结的 HSV 2 RGB 算法链接
ShaderToy系列HSV