Unity中实现ShaderToy卡通火(一)

文章目录

  • 前言
  • 一、准备好我们的后处理基础脚本
    • 1、C#:
    • 2、Shader:
  • 二、开始逐语句对ShaderToy进行转化
    • 1、首先,找到我们的主函数 mainImage
    • 2、其余的方法全部都是在 mainImage 函数中调用的方法
    • 3、替换后的代码(已经没报错了,都是效果不对)


前言

在上一篇文章中,我们讲解了基础的ShaderToy怎么转化为Unity中的Shader。我们在这篇文章中,复刻一个复杂的ShaderToy效果卡通火。

  • Unity中的ShaderToy

  • 卡通火

请添加图片描述


一、准备好我们的后处理基础脚本

1、C#:

using UnityEngine;

//后处理脚本
[ExecuteInEditMode]
public class P2_9 : MonoBehaviour
{
    public Shader PostProcessingShader;
    private Material mat;
    public Material Mat
    {
        get
        {
            if (PostProcessingShader == null)
            {
                Debug.LogError("没有赋予Shader");
                return null;
            }
            if (!PostProcessingShader.isSupported)
            {
                Debug.LogError("当前Shader不支持");
                return null;
            }
            //如果材质没有创建,则根据Shader创建材质,并给成员变量赋值存储
            if (mat == null)
            {
                Material _newMaterial = new Material(PostProcessingShader);
                _newMaterial.hideFlags = HideFlags.HideAndDontSave;
                mat = _newMaterial;
                return _newMaterial;
            }
            return mat;
        }
    }

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        Graphics.Blit(source,destination,Mat);
    }
}

2、Shader:

Shader "MyShader/P2_9"
{
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #include "UnityCG.cginc"
            
            fixed4 frag (v2f_img i) : SV_Target
            {
                
                return 1;
            }
            ENDCG
        }
    }
}

二、开始逐语句对ShaderToy进行转化

1、首先,找到我们的主函数 mainImage

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 uv = fragCoord.xy / iResolution.xy;
    uv.x *= 4.0;
    float t = iTime * 3.0;    
    vec3 col = vec3(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 = vec4(vec3(CUTOFF),1.0);   
    
    if (noise < CUTOFF){       
		//black
        col = vec3(0.);
    }else{
		//fire
        float d = pow(getDepth(noise),0.7);        
        vec3 hsv = vec3(d *0.17,0.8 - d/4., d + 0.8);
        col = hsv2rgb(hsv);
	}
    
    fragColor = vec4(col,1.0);   
}

2、其余的方法全部都是在 mainImage 函数中调用的方法

因此,我们可以直接使用把这些方法复制到 我们片元着色器的上方,把参数类型转化为CG中的参数类型,即可直接使用

  • vec2 :float2
  • vec3 :float3
  • vec4 :float4
  • float4(0,0) : 0
  • fract(x) : frac(x) (取 x 的小数部分)
  • mix(a,b,x) :lerp(a,b,x) (线性插值)

选中需要转化的变量名,使用快捷键 Ctrl + F,进行全部替换

在这里插入图片描述

3、替换后的代码(已经没报错了,都是效果不对)

//https://www.shadertoy.com/view/lsscWr

Shader "MyShader/P2_9"
{
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag
            #include "UnityCG.cginc"

            float3 mod289(float3 x)
            {
                return x - floor(x * (1.0 / 289.0)) * 289.0;
            }

            float4 mod289(float4 x)
            {
                return x - floor(x * (1.0 / 289.0)) * 289.0;
            }

            float4 permute(float4 x)
            {
                return mod289(((x * 34.0) + 1.0) * x);
            }

            float4 taylorInvSqrt(float4 r)
            {
                return 1.79284291400159 - 0.85373472095314 * r;
            }

            float snoise(float3 v)
            {
                const float2 C = float2(1.0 / 6.0, 1.0 / 3.0);
                const float4 D = float4(0.0, 0.5, 1.0, 2.0);

                // First corner
                float3 i = floor(v + dot(v, C.yyy));
                float3 x0 = v - i + dot(i, C.xxx);

                // Other corners
                float3 g = step(x0.yzx, x0.xyz);
                float3 l = 1.0 - g;
                float3 i1 = min(g.xyz, l.zxy);
                float3 i2 = max(g.xyz, l.zxy);

                //   x0 = x0 - 0.0 + 0.0 * C.xxx;
                //   x1 = x0 - i1  + 1.0 * C.xxx;
                //   x2 = x0 - i2  + 2.0 * C.xxx;
                //   x3 = x0 - 1.0 + 3.0 * C.xxx;
                float3 x1 = x0 - i1 + C.xxx;
                float3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
                float3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y

                // Permutations
                i = mod289(i);
                float4 p = permute(permute(permute(
                            i.z + float4(0.0, i1.z, i2.z, 1.0))
                        + i.y + float4(0.0, i1.y, i2.y, 1.0))
                    + i.x + float4(0.0, i1.x, i2.x, 1.0));

                // Gradients: 7x7 points over a square, mapped onto an octahedron.
                // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
                float n_ = 0.142857142857; // 1.0/7.0
                float3 ns = n_ * D.wyz - D.xzx;

                float4 j = p - 49.0 * floor(p * ns.z * ns.z); //  mod(p,7*7)

                float4 x_ = floor(j * ns.z);
                float4 y_ = floor(j - 7.0 * x_); // mod(j,N)

                float4 x = x_ * ns.x + ns.yyyy;
                float4 y = y_ * ns.x + ns.yyyy;
                float4 h = 1.0 - abs(x) - abs(y);

                float4 b0 = float4(x.xy, y.xy);
                float4 b1 = float4(x.zw, y.zw);

                //float4 s0 = float4(lessThan(b0,0.0))*2.0 - 1.0;
                //float4 s1 = float4(lessThan(b1,0.0))*2.0 - 1.0;
                float4 s0 = floor(b0) * 2.0 + 1.0;
                float4 s1 = floor(b1) * 2.0 + 1.0;
                float4 sh = -step(h, 0);

                float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
                float4 a1 = b1.xzyw + s1.xzyw * sh.zzww;

                float3 p0 = float3(a0.xy, h.x);
                float3 p1 = float3(a0.zw, h.y);
                float3 p2 = float3(a1.xy, h.z);
                float3 p3 = float3(a1.zw, h.w);

                //Normalise gradients
                float4 norm = taylorInvSqrt(float4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
                p0 *= norm.x;
                p1 *= norm.y;
                p2 *= norm.z;
                p3 *= norm.w;

                // Mix final noise value
                float4 m = max(0.6 - float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0);
                m = m * m;
                return 42.0 * dot(m * m, float4(dot(p0, x0), dot(p1, x1),
                 dot(p2, x2), dot(p3, x3)));
            }

            //END ASHIMA /

            const float STEPS = 4.;
            float CUTOFF = 0.15; //depth less than this, show black

            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);
            }

            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;
            }

            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);

                //step it
                d = floor(d * STEPS) / STEPS;

                return d;
            }


            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);
            }
            ENDCG
        }
    }
}

在这里插入图片描述


我们在下篇文章中,调试一下Shader问题出在了哪?

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

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

相关文章

渲染技术在虚拟仿真中的应用

虚拟仿真&#xff08;Virtual Reality&#xff09;是一种仿真技术&#xff0c;它使用计算机生成一个虚拟世界&#xff0c;用户可以通过各种传感通道与这个虚拟世界进行自然的交互。虚拟仿真技术可以创建和体验虚拟世界&#xff0c;使用户可以像在真实世界中一样进行操作和体验。…

Python将字典列表导出为Excel文件的方法

将如下的字典列表内容导出为Excel表格文件形式&#xff1a; python将字典列表导出为Excel文件的方法&#xff0c;如下所示&#xff1a; 1、安装python官方Excel库------xlwt 直接在终端进行安装即可&#xff1a;pip install xlwt 安装完成后&#xff0c;在程序中引入xlwt的库…

ke14--10章-1数据库JDBC介绍

注册数据库(两种方式),获取连接,通过Connection对象获取Statement对象,使用Statement执行SQL语句。操作ResultSet结果集 ,回收数据库资源. 需要语句: 1Class.forName("DriverName");2Connection conn DriverManager.getConnection(String url, String user, String…

CGAN笔记总结第二弹~

CGAN原理与源码分析 一、复习GAN1.1损失函数1.2判别器源码1.3 生成器源码 二、什么是CGAN&#xff1f;2.1 CGAN原理图2.2条件GAN的损失函数2.3 生成器源码2.4 判别器源码2.5 训练过程1&#xff09;这里的训练顺序2&#xff09;为什么先训练判别器后训练生成器呢&#xff1f; 2.…

Python学习笔记-类

1 定义类 类是函数的集合&#xff0c;class来定义类 pass并没有实际含义&#xff0c;只是为了代码能执行通过&#xff0c;不报错而已&#xff0c;相当于在代码种占一个位置&#xff0c;后续完善 类是对象的加工厂 2.创建对象 carCar()即是创建对象的过程 3、类的成员 3.1 实例…

PC 机与单片机通信(RS232 协议)

PC 机与单片机通信(RS232 协议) 目录&#xff1a; 1、单片机串口通信的应用 2、PC控制单片机IO口输出 3、单片机控制实训指导及综合应用实例 4、单片机给计算机发送数据&#xff1a; [实验任务] 单片机串口通信的应用&#xff0c;通过串口&#xff0c;我们的个人电脑和单…

操作系统大会 openEuler Summit 2023即将召开,亮点不容错过

【12月11日&#xff0c;北京】数字化、智能化浪潮正奔涌而来。操作系统作为数字基础设施的底座&#xff0c;已经成为推动产业数字化、智能化发展的核心力量&#xff0c;为数智未来提供无限可能。12月15-16日&#xff0c;以“崛起数字时代 引领数智未来”为主题的操作系统大会 &…

双向链表(数据结构与算法)

✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ &#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1…

香港身份(户口)大放水!23年香港优才计划、高才通计划申请数据公开!24年冲!

香港身份&#xff08;户口&#xff09;大放水&#xff01;23年香港优才计划、高才通计划申请数据公开&#xff01;24年冲&#xff01; 近期香港入境处公布了各项人才入境计划申请及审批数字&#xff0c;: 截止今年10月31日一共有18.4万宗申请各类人才输入计划&#xff0c;获批人…

IntelliJ IDEA无公网远程连接Windows本地Mysql数据库提高开发效率

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;…

智能优化算法应用:基于蝴蝶算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蝴蝶算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蝴蝶算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝴蝶算法4.实验参数设定5.算法结果6.参考文献7.MA…

【深度学习】注意力机制(三)

本文介绍一些注意力机制的实现&#xff0c;包括EMHSA/SA/SGE/AFT/Outlook Attention。 【深度学习】注意力机制&#xff08;一&#xff09; 【深度学习】注意力机制&#xff08;二&#xff09; 目录 一、EMHSA&#xff08;Efficient Multi-Head Self-Attention&#xff09;…

logstash插件简单介绍

logstash插件 输入插件(input) Input&#xff1a;输入插件。 Input plugins | Logstash Reference [8.11] | Elastic 所有输入插件都支持的配置选项 SettingInput typeRequiredDefaultDescriptionadd_fieldhashNo{}添加一个字段到一个事件codeccodecNoplain用于输入数据的…

可学习超图拉普拉斯算子代码

python版本&#xff1a;3.6。sklearn版本&#xff1a;scikit-learn0.19 问题1&#xff1a;ERROR: Could not build wheels for ecos, scs, which is required to install pyproject.toml-based projects| 解决办法&#xff1a;cvxpy安装过程中遇到的坑_ecos 2.0.7.post1 cp37 …

Terraform实战(二)-terraform创建阿里云资源

1 初始化环境 1.1 创建初始文件夹 $ cd /data $ mkdir terraform $ mkdir aliyun terraform作为terraform的配置文件夹&#xff0c;内部的每一个.tf&#xff0c;.tfvars文件都会被加载。 1.2 配置provider 创建providers.tf文件&#xff0c;配置provider依赖。 provider…

LeetCode 每日一题 Day 9 ||简单dp

70. 爬楼梯 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1 阶 1 阶2 阶 示例 2&am…

智能井盖传感器怎么有效监测井盖位移

随着城市化进程的加速推进&#xff0c;城市基础设施的安全与维护问题日益凸显&#xff0c;引发了社会的广泛关注。其中井盖作为城市地下设施的重要一环&#xff0c;其安全问题时刻影响着市民的幸福生活。近年来智能井盖传感器的发展与应用为实时监测井盖位移提供了全新的解决方…

嵌入式开发按怎样的路线学习较好?

嵌入式开发按怎样的路线学习较好&#xff1f; 在开始前我有一些资料&#xff0c;是我根据自己从业十年经验&#xff0c;熬夜搞了几个通宵&#xff0c;精心整理了一份「嵌入式从专业入门到高级教程工具包」&#xff0c;点个关注&#xff0c;全部无偿共享给大家&#xff01;&…

BigData之Google Hadoop中间件安装

前言 Hadoop / Zookeeper / Hbase 因资源有限 这三个都是安装在同一台Centos7.9的机器上 但通过配置 所以在逻辑上是distributed模式 1 Java安装 1.1 下载java11 tar/opt/java/jdk-11.0.5/ 1.2 环境配置修改 文件/etc/profile export JAVA_HOME/opt/java/jdk-11.0.5/ e…

网络层重点协议——IP协议详解

✏️✏️✏️今天给大家分享的是网络层的重点协议——IP协议。 清风的CSDN博客 &#x1f6e9;️&#x1f6e9;️&#x1f6e9;️希望我的文章能对你有所帮助&#xff0c;有不足的地方还请各位看官多多指教&#xff0c;大家一起学习交流&#xff01; ✈️✈️✈️动动你们发财的…