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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yolov8实战第二天——yolov8训练结果分析(保姆式解读)

yolov8实战第一天——yolov8部署并训练自己的数据集&#xff08;保姆式教程&#xff09;-CSDN博客 我们在上一篇文章训练了一个老鼠的yolov8检测模型&#xff0c;训练结果如下图&#xff0c;接下来我们就详细解析下面几张图。 一、混淆矩阵 正确挑选&#xff08;正确&#…

C#串口通讯

在C#写串口通讯小程序时&#xff0c;可以使用System.IO.Ports命名空间提供的SerialPort类。下面是一个简单的例子&#xff0c;包含了一个基本的UI&#xff0c;用于设置串口参数和进行通讯。这里使用了Windows Forms&#xff08;WinForms&#xff09;来创建UI。 步骤&#xff1…

数据结构——队列

目录 一、队列的定义 二、队列的实现 1. 队列的顺序存储结构 1.1. 顺序队 1. 创建顺序队 2. 删除顺序队 3. 判断队列是否为空 4. 判断队列是否已满 5. 入队 6. 出队 7. 获取队列长度 8. 获取队首元素 1.2. 环形队 1. 创建环形队 2. 删除环形队 3. 判断环形队列…

C++导出C标准的dll动态库

1 新建项目 1.1 使用VS新建一个空项目 1.2 在属性页中将配置类型改为&#xff1a;动态库(dll) 2 添加头文件 添加文件Api.h&#xff0c;示例代码如下 #pragma once#define DLLEXPORT __declspec(dllexport)extern "C" {DLLEXPORT int getAdd(int a, int b); //求…

C++中的多态你真的了解吗?多态原理全面具体讲解

目录 1. 多态的概念 2. 多态的定义及实现 2.1 多态的构成条件 2.2 虚函数 2.3 虚函数的重写 2.4 C11 override 和 final 2.5 重载、覆盖(重写)、隐藏(重定义)的对比 3. 抽象类 3.1 概念 4. 多态的原理 4.1 虚函数表 4.2多态的原理 4.3 动态绑定与静态绑定 5. 单继…

使用helpdesk帮助台有什么好处?

Helpdesk帮助台是一套帮助IT团队管理IT工单生命周期、自动化日常工作、优化工作流程的集合&#xff0c;它可以帮助IT团队提高生产力、降低成本、改善服务水平和客户体验。 而helpdesk帮助台管理软件所带来的好处不仅限于IT运营&#xff0c;所有利益相关者都会受益&#xff0c;…

【C语言必学知识点五】指针

指针 导言一、指针与指针变量二、指针变量的创建和指针类型三、指针类型的意义3.1 指针 /- 整数3.2 指针解引用 四、野指针4.1 定义4.2 野指针的成因4.3 指针未初始化4.4 指针越界访问4.5 指针指向的空间被释放4.6 如何规避野指针 五、指针运算5.1指针-整数5.2 指针-指针5.2.1 …

短剧分销平台开发,打造短剧内容变现新模式

短剧目前已经成为了影视行业中的一匹黑马&#xff0c;短剧主要是根据爽文小说翻拍&#xff0c;将小说中精彩高潮的剧情翻拍成短剧爽文&#xff0c;使得观众沉浸在短剧中&#xff0c;欲罢不能&#xff01; 短剧分销平台是短剧推广的新模式&#xff0c;它打破了传统的分销模式。…

代码随想录算法训练营 | day51 动态规划 309.最佳买卖股票时机含冷冻期,714.买卖股票的最佳时机含手续费

刷题 309.最佳买卖股票时机含冷冻期 题目链接 | 文章讲解 | 视频讲解 题目&#xff1a;给定一个整数数组&#xff0c;其中第 i 个元素代表了第 i 天的股票价格 。 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多…

启动cad显示丢失mfc140u.dll怎么办?mfc140u.dll丢失有效解决方法分享

在CAD软件或其他软件中&#xff0c;有时候会出现由于找不到mfc140u.dll文件而无法执行代码的错误提示。这个问题可能是由于多种原因引起的&#xff0c;例如文件损坏、缺失或被病毒感染等。下面将介绍五个常见的解决方法&#xff0c;并解释mfc140u.dll丢失的原因以及该文件对CAD…

7-1 六度空间 (PTA-数据结构)

“六度空间”理论又称作“六度分隔&#xff08;Six Degrees of Separation&#xff09;”理论。这个理论可以通俗地阐述为&#xff1a;“你和任何一个陌生人之间所间隔的人不会超过六个&#xff0c;也就是说&#xff0c;最多通过五个人你就能够认识任何一个陌生人。”如图1所示…

Openwrt源码下载出现“The remote end hung up unexpected”

最近项目原因需要下载openwrt21.02版本源码&#xff0c;花费了很多时间&#xff0c;找到正确方法后&#xff0c;发现可以节省很多时间&#xff0c;记录下过程&#xff0c;方便自己&#xff0c;可能方便他人。 一.问题阐述 openwrt21.02下载链接如下&#xff1a; git clone -…

Python从入门到精通六:Python数据容器

数据容器入门 为什么学习数据容器 思考一个问题&#xff1a;如果我想要在程序中&#xff0c;记录5名学生的信息&#xff0c;如姓名。 如何做呢&#xff1f; 学习数据容器&#xff0c;就是为了批量存储或批量使用多份数据 Python中的数据容器&#xff1a; 一种可以容纳多份…

直播美颜SDK开发实战:从入门到精通

直播美颜SDK的应用已经成为许多直播平台和开发者关注的焦点。本文将带领读者深入探讨直播美颜SDK的开发实战&#xff0c;从入门到精通的过程。 1.引言 直播美颜SDK是一种集成了图像处理、人脸识别、滤镜算法等技术的开发工具包。通过使用该SDK&#xff0c;开发者能够为直播应…

深度学习 Day14——P3天气识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 文章目录 前言1 我的环境2 代码实现与执行结果2.1 前期准备2.1.1 引入库2.1.2 设置GPU&#xff08;如果设备上支持GPU就使用GPU,否则使用C…

2023 re:Invent使用 PartyRock 和 Amazon Bedrock 安全高效构建 AI 应用程序

前言 本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 亚马逊云科技开发者社区, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 “Your Data, Your AI, Your Future.&#xff08;你的数据&#xff0c;你的AI&…

HarmonyOS保存应用数据

数据管理 1 概述 在移动互联网蓬勃发展的今天&#xff0c;移动应用给我们生活带来了极大的便利&#xff0c;这些便利的本质在于数据的互联互通。因此在应用的开发中数据存储占据了非常重要的位置&#xff0c;HarmonyOS应用开发也不例外。 本文将为您介绍HarmonyOS提供的数据管…

统信UOS上图形化配置系统和应用代理

原文链接&#xff1a;统信UOS上图形化配置系统和应用代理 hello&#xff0c;大家好啊&#xff0c;今天我要给大家介绍的是在统信UOS操作系统上如何通过图形化界面配置系统代理和应用代理。在许多公司的内网环境中&#xff0c;直接访问互联网可能受到限制&#xff0c;但通常会提…

智慧工地源码:为施工企业提供专业落地的解决方案

智慧工地利用物联网、大数据、AI等核心技术&#xff0c;实时采集现场数据&#xff0c;自动分析&#xff0c;精准分析、智能决策、科学评价&#xff0c;形成一套数据驱动的新型管理模式。为施工企业提供生产提效、安全可控、成本节约的项目管理解决方案&#xff0c;提升项目部管…

关于linux 磁盘占用排查问题

1.关于磁盘 查看整体磁盘占用大小 df -h 2. 先排除mysql 数据大小 查询库的大小 SELECT table_schema AS "Database", ROUND(SUM(data_length index_length) / 1024 / 1024, 2) AS "Size (MB)" FROM information_schema.TABLES GROUP BY table_schema…