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)
                {
                    //black
                    col = 0;
                }
                else
                {
                    //fire
                    float 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)
{
	//black
	col = 0;
}
else
{
	//fire
	float 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)
	{
		 //black
		col = 0;
	}
	else
	{
		//fire
		//计算得到 火的轮廓
		float d = pow(getDepth(noise), 0.7);
		//计算得到 色相、明度、饱和度
		loat3 hsv = float3(d * 0.17, 0.8 - d / 4., d + 0.8);
		//将 HSV 转化为 RGB
		col = 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 upwards
	
	float TRAVEL_SPEED = 1.5;
	
	//octave 1
	float SCALE = 2.0;
	float noise = snoise(float3(uv.x * SCALE, uv.y * SCALE - t * TRAVEL_SPEED, 0));
	
	//octave 2 - more detail
	SCALE = 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

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

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

相关文章

如何进行产品数据分析一——移动应用APP分析方法

如何进行产品数据分析 产品的定义产品分析的构成移动应用APP分析方法AARRR1.流量拆解DAUMAU活跃率拆解流量深度 2.流量引入反作弊算法识别系统&#xff08;量&#xff09;拉新质量评估体系&#xff08;质&#xff09;渠道价值评估体系&#xff08;值&#xff09; 3.流量输出 产…

[MySQL]事务原理之redo log,undo log

&#x1f308;键盘敲烂&#xff0c;年薪30万&#x1f308; 目录 一、log日志文件 &#x1f4d5; 事务执行流程 &#x1f4d5; redo log &#x1f4d5; undo log 二、总结 &#x1f440;再来一遍ACID 1. 原子性&#xff1a;原子性确保事务作为一个整体执行&#xff0c;要么…

D4140交流插座电器漏电断路器的低功耗控制芯片,内置桥式整流器漏电灵敏度可调,采用SOP8和DIP8 的封装形式

D4140 是一种用于交流插座电器漏电断路器的低功耗控制器。这些设备可以检测到接地的危险电流路径&#xff0c;例如设备掉进水中。在发生有害或致命的电击之前&#xff0c;断路器会断开线路。内置有整流桥&#xff0c;齐纳管稳压器&#xff0c;运算放大器&#xff0c;电流基准&a…

【数学建模美赛M奖速成系列】报名流程与论文的基本格式

数学建模美赛M奖速成系列 写在前面报名方式1.官网直接报名2.赛氪软件辅助报名 论文的基本格式摘要模型建立模型求解结果分析与检验模型评价 竞赛的基本注意事项1. 选题后查找资料2. 写作能力和编程能力 历年优秀论文标题与摘要简明扼要善用图表 最后 写在前面 最近&#xff0c…

【Docker】学习笔记(一)三剑客之 docker engine仓库、镜像与容器的基本操作

docker engine安装 ubuntu20.04安装docker教程 docker核心架构 镜像&#xff08;image&#xff09; 一个镜像就代表一个软件服务&#xff08;ubuntu镜像、mysql镜像、redis镜像、mq镜像&#xff09;只读 远程中心仓库&#xff08;repository&#xff09; 中心仓库用来集中存储…

5.1CPU的功能和结构

CPU的功能 1.指令控制。 完成取指令、分析指令和执行指令的操作&#xff0c;即程序的顺序控制。 ⒉操作控制。 一条指令的功能往往是由若干操作信号的组合来实现的。CPU管理并产生由内存取出的每条指令的操作信号&#xff0c;把各种操作信号送往相应的部件&#xff0c;从而控制…

微信小程序:上传图片到别的域名文件下

效果 wxml <!-- 上传照片 --> <view class"addbtn"><view classpic name"fault_photo" wx:for"{{imgs}}" wx:for-item"item" wx:key"*this"><image classweui-uploader_img src"{{item}}"…

程序员必须知晓的11个C++要点-供大家学习研究参考

要点汇集C书中或网站上无法找到的&#xff0c;如&#xff1a;指向成员的指针&#xff0c;这是许多资料中都不愿提到的地方&#xff0c;也是经常出错的地方。希望对大家学习研究有帮助。 要点1: <iostream.h> 还是 <iostream>? 要点2&#xff1a;用引用传递参数时…

若依 ruoyi-vue3+ts-plus+ 宇道 yudao-ruoyi-vue-pro前端显示部门名称

想在 index.vue 上显示列表里对应的部门名称 效果 引入dept import * as DeptApi from "/api/system/dept"; 初始化时 /** 初始化 **/ onMounted(async () > {getList();deptNameList.value await DeptApi.getSimpleDeptList(); }) 加载id 对应的部门名称 …

网络推理之深度学习推理框架

如何选择深度学习推理框架&#xff1f; PyTorch vs LibTorch&#xff1a;网络推理速度谁更快&#xff1f; 高质量C进阶[2]&#xff1a;如何让线性代数加速1000倍&#xff1f; TensorRT: ONNX:

AI日报:人工智能与新材料的发现

文章目录 总览人工智能正在革命性地发现新的或更强的材料&#xff0c;这将改变制造业。更坚韧的合金问题研究解决方案 新材料人工智能存在的挑战方法探索 日本的研究人员正在使用人工智能制造更强的金属合金或发现新材料&#xff0c;并彻底改变制造过程 总览 日本的研究人员开…

【C】⽂件操作

1. 为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久化…

鸿蒙原生应用/元服务开发-Stage模型能力接口(二)

ohos.app.ability.AbilityConstant (AbilityConstant)一、说明 AbilityConstant提供Ability相关的枚举&#xff0c;包括设置初次启动原因、上次退出原因、迁移结果、窗口类型等。本模块首批接口从API version 9开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口…

【Java 基础】32 定时调度

文章目录 Timer 类创建 Timer注意事项 ScheduledExecutorService 接口创建 ScheduledExecutorService注意事项 选择合适的定时调度方式Timer 的适用场景ScheduledExecutorService 的适用场景 总结 在软件开发中&#xff0c;定时任务是一种常见的需求&#xff0c;用于周期性地执…

替代升级虚拟化 | ZStack Cloud云平台助力康恩贝核心业务上云

数字经济正加速推动各行各业的高质量升级发展&#xff0c;云计算是数字经济的核心底层基础设施。作为云基础软件企业&#xff0c;云轴科技ZStack 坚持自主创新&#xff0c;自研架构&#xff0c;产品矩阵可全面覆盖数据中心云基础设施&#xff0c;针对虚拟化资源实现纳管、替代和…

大数据技术之Shell(超级详细)

大数据技术之Shell&#xff08;超级详细&#xff09; 第1章 Shell概述 Shell 是一种脚本语言&#xff0c;用于在操作系统的命令行界面&#xff08;CLI&#xff09;下执行命令和脚本。在大数据领域&#xff0c;Shell 脚本常用于编写数据处理和分析任务的自动化脚本&#xff0c…

java swing 药品销售系统 mysql

数据库 查询药品&#xff1a; 出售药品&#xff1a; 查询客户信息&#xff1a; 查询订单信息&#xff1a;

Next.js ts redux/toolkit状态管理

目录 介绍 安装依赖 初始化store 1、在src下创建store文件夹&#xff0c; 2、创建最简单的slice切片 3、创建入口文件index.ts 4、创建hooks.ts 在_app.tsx中注入store tsx中使用store payload createAsyncThunk 效果 介绍 reduxjs/toolkit是Redux 官方提供的一个…

Axure元件基本介绍进阶

Axure元件基本介绍进阶 1.Axure元件基本介绍1.在 Axure 中&#xff0c;元件是构建原型的基本构成单元&#xff0c;能够帮助设计师快速创建、重复使用和管理设计元素。以下是 Axure 中元件的基本介绍&#xff1a;1.基本元件&#xff1a; 2.基本元件的使用一.【举例说明】积木&am…

Python提取速率

Python提取速率 需求&#xff1a;提取速率需要有M提取到M前数值并添加回原始数据如果是0只能为空白 Python实现 import pandas as pd import os# 提取速率函数 def extract_broadband_speed(speed):if pd.notnull(speed) and M in str(speed):return str(speed).split(M)[0] …