当前位置: 首页 > news >正文

Unity中实现ShaderToy卡通火(原理实现篇)

文章目录

  • 前言
  • 一、我们在片元着色器中,实现卡通火的大体框架
    • 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部分(显示 火的形状 和 火的着色)

  1. hsv2rgb : 由 hsv 转化为 RGB 色
    请添加图片描述

  2. hsv : 色相、饱和度、亮度
    请添加图片描述

  3. d :使用pow调节色阶范围

  4. 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噪声笔记
    这里引用一篇别人的笔记,作为该噪音函数的讲解

  1. 第一次噪波效果
    请添加图片描述
  2. 第二次噪波效果
    请添加图片描述
  3. 两次噪波叠加效果
    请添加图片描述
  4. 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

相关文章:

Unity中实现ShaderToy卡通火(原理实现篇)

文章目录 前言一、我们在片元着色器中&#xff0c;实现卡通火的大体框架1、使用 noise 和 _CUTOFF 判断作为显示火焰的区域2、_CUTOFF &#xff1a; 用于裁剪噪波范围的三角形3、noise getNoise(uv, t); : 噪波函数 二、顺着大体框架依次解析具体实现的功能1、 uv.x * 4.0; : …...

引迈信息-JNPF平台怎么样?值得入手吗?

目录 1.前言 2.引迈低代码怎么样&#xff1f; 3.平台亮点展示 4.引迈产品特点 5.引迈产品技术栈&#xff1a; 1.前言 低代码是近几年比较火的一种应用程序快速开发方式&#xff0c;它能帮助用户在开发软件的过程中大幅减少手工编码量&#xff0c;并通过可视化组件加速应用…...

大数据云计算——使用Prometheus-Operator进行K8s集群监控

大数据云计算——使用Prometheus-Operator进行K8s集群监控 一、 背景 在非operator配置的普罗中我们监控k8s集群都是通过配置configmap进行服务发现和指标拉取。切换到prometheus-operator难免会有些使用问题。不少用户已经习惯底层配置自动发现的方式。当过渡到servicemonit…...

[蓝桥杯刷题]合并区间、最长不连续子序列、最长不重复数组长度

前言 ⭐Hello!这里是欧_aita的博客。 ⭐今日语录: 成功的关键在于对目标的持久追求。 ⭐个人主页&#xff1a;欧_aita ψ(._. )>⭐个人专栏&#xff1a; 数据结构与算法 数据库 文章目录 前言合并区间问题&#x1f4d5;现实应用大致思路代码实现代码讲解 最长不连续子序列&a…...

Hazel引擎学习(十二)

我自己维护引擎的github地址在这里&#xff0c;里面加了不少注释&#xff0c;有需要的可以看看 参考视频链接在这里 这是这个系列的最后一篇文章&#xff0c;Cherno也基本停止了Games Engine视频的更新&#xff0c;感觉也差不多了&#xff0c;后续可以基于此项目开发自己想要…...

中文字符串逆序输出

今天碰到这个题&#xff0c;让我逆序输出中文字符串&#xff0c;可给我烦死了&#xff0c;之前没有遇到过&#xff0c;也是查了资料才知道&#xff0c;让我太汗颜了。 英文字符串逆序输出很容易&#xff0c;开辟一块空间用来存放逆序后的字符串&#xff0c;从后往前遍历原字符串…...

MySQL BinLog 数据还原恢复

博文目录 文章目录 查看状态查看 binlog 开关及存储路径查看 binlog 配置 如 存储格式 binlog_format查看当前还存在的日志查看当前正在使用的日志 切换日志确定日志确定日志文件日志格式改写日志简要说明确定日志位置以事件为单位查看日志分析日志 还原数据 查看状态 查看 b…...

理想汽车校招内推--大量hc等你来

投递链接: https://li.jobs.feishu.cn/s/i8BLJE1j 欢迎大家投递...

RabbitMQ死信队列详解

什么是死信队列 由于特定的**原因导致 Queue 中的某些消息无法被消费&#xff0c;**这类消费异常的数据将会保存在死信队列中防止消息丢失&#xff0c;例如用户在商城下单成功并点击支付后&#xff0c;在指定时间未支付时的订单自动失效死信队列只不过是绑定在死信交换机上的队…...

计算机网络:物理层(编码与调制)

今天又学会了一个知识&#xff0c;加油&#xff01; 目录 一、基带信号与宽带信号 1、基带信号 2、宽带信号 3、选择 4、关系 二、数字数据编码为数字信号 1、非归零编码【NRZ】 2、曼彻斯特编码 3、差分曼彻斯特编码 4、归零编码【RZ】 5、反向不归零编码【NRZI】 …...

嵌入式开发板qt gdb调试

1&#xff09; 启动 gdbserver ssh 或者 telnet 登陆扬创平板 192.168.0.253&#xff0c; 进入命令行执行如下&#xff1a; chmod 777 /home/HelloWorld &#xff08;2&#xff09; 打 开 QTcreator->Debug->StartDebugging->Attach to Running Debug Server 进行…...

基于python实现原神那维莱特开转脚本

相信不少原友都抽取了枫丹大C那维莱特&#xff0c;其强力的输出让不少玩家爱不释手。由于其转的越快&#xff0c;越不容易丢伤害的特点&#xff0c;很多原友在开转时容易汗流浃背&#xff0c;所以特意用python写了一个自动转圈脚本&#xff0c;当按住鼠标侧键时&#xff0c;即可…...

C# 实现Lru缓存

C# 实现Lru缓存 LRU 算法全称是最近最少使用算法&#xff08;Least Recently Use&#xff09;&#xff0c;是一种简单的缓存策略。 通常用在对象池等需要频繁获取但是又需要释放不用的地方。 代码实现的基本原理就是使用链表&#xff0c;当某个元素被访问时&#xff08;Get或…...

牛客网BC107矩阵转置

答案&#xff1a; #include <stdio.h> int main() {int n0, m0,i0,j0,a0,b0;int arr1[10][10]{0},arr2[10][10]{0}; //第一个数组用来储存原矩阵&#xff0c;第二个数组用来储存转置矩阵scanf("%d%d",&n,&m); if((n>1&&n<10)&&am…...

协作办公原来如此简单?详解 ONLYOFFICE 协作空间 2.0 更新

协作办公原来如此简单&#xff1f;详解 ONLYOFFICE 协作空间 2.0 更新 上周&#xff0c;ONLYOFFICE 的协作空间推出升级版 2.0 版本了&#xff1a; ONLYOFFICE 协作空间 2.0 现已发布&#xff1a;新增公共房间、插件、重新分配数据、RTL 界面等功能 ONLYOFFICE 协作空间是去…...

2023年国赛高教杯数学建模A题定日镜场的优化设计解题全过程文档及程序

2023年国赛高教杯数学建模 A题 定日镜场的优化设计 原题再现 构建以新能源为主体的新型电力系统&#xff0c;是我国实现“碳达峰”“碳中和”目标的一项重要措施。塔式太阳能光热发电是一种低碳环保的新型清洁能源技术[1]。   定日镜是塔式太阳能光热发电站&#xff08;以下…...

c/c++ 结构体、联合体、枚举

结构体 结构体内存对齐规则&#xff1a; 1、结构体的第一个成员对齐到结构体变量起始位置偏移量为0的地址处 2、其他成员变量要对齐到某个数字&#xff08;对齐数&#xff09;的整数倍的地址处。 对齐数&#xff1a;编译器默认的一个对齐数与该成员变量大小的较小值。 vs 中…...

stl模板库成员函数重载类型混肴编译不通过解决方法

stl模板库成员函数重载类型混肴编译不通过解决方法 这种方式编译不通过IsArithmetic和HasMemberList编译器存在混肴 template <typename T, typename Enable std::enable_if<IsArithmetic<T>::value>::type >static void DumpWrapper(T* filed, std::strin…...

MySQL——表的约束

目录 一.表的约束 二.空属性 ​编辑三.默认值 四.列描述 五.主键 1.主键 2.符合主键 六.自增长 七.唯一键 八.外键 一.表的约束 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&…...

cordic 算法学习记录

参考&#xff1a;b站教学视频FPGA&#xff1a;Cordic算法介绍与实现_哔哩哔哩_bilibili FPGA硬件实现加减法、移位等操作比较简单&#xff0c;但是实现乘除以及函数计算复杂度高且占用资源多&#xff0c;常见的计算三角函数/平方根的求解方式有①查找表&#xff1a;先把函数对应…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。

2024 年&#xff0c;高端封装市场规模为 80 亿美元&#xff0c;预计到 2030 年将超过 280 亿美元&#xff0c;2024-2030 年复合年增长率为 23%。 细分到各个终端市场&#xff0c;最大的高端性能封装市场是“电信和基础设施”&#xff0c;2024 年该市场创造了超过 67% 的收入。…...

【Linux】使用1Panel 面板让服务器定时自动执行任务

服务器就是一台24小时开机的主机&#xff0c;相比自己家中不定时开关机的主机更适合完成定时任务&#xff0c;例如下载资源、备份上传&#xff0c;或者登录某个网站执行一些操作&#xff0c;只需要编写 脚本&#xff0c;然后让服务器定时来执行这个脚本就可以。 有很多方法实现…...