2.8Flowmap的实现

一、Flowmap 是什么

半条命2中水的流动

求生之路2中的水的流动

这种方式原理简单,容易实现,运算量少,如今也还在使用

1.flowmap的实质

Flow map(流向图) ,一张记录了2D向量信息的纹理,Flow map上的颜色(通常为RG通道)记录该处向量场的方向,让模型上某一点表现出定量流动的特征。

通过在shader中偏移uv再对纹理进行采样,来模拟流动效果。

右边向量场的方向于中间Flowmap和它的方向是不一致的,这是为什么呢?

2.前置了解:UV映射

UV坐标用于查找纹理的颜色值:

UV贴图(用于理解):使用(R,G)颜色通道表示坐标:

黑色(0,0),绿色处(0,1),红色处(1,0),黄色处(1,1)

如果我们要对一个矩形进行纹理查找的话,我们首先会用到它的UV坐标

左边为unity中的UV坐标 与我们熟知的xy坐标轴相似

用该UV坐标去查找右边这张贴图的颜色值,我们将会得到和原贴图一摸一样的结果

如果让更改UV坐标,让每一列都拥有相同的UV值再去采样,则会得到右图这样的条纹图结果

若使整个采样的时候用的UV值是同一个的话,如图我们将该UV坐标的UV值全都变为黑色,那么结果就会对左下角进行采样

UV贴图上颜色相同的地方就意味着它在采样纹理的时候使用了同一个位置

Flowmap则是通过它上面所带有的向量场的信息对UV进行一个偏移之后,去干扰我们采样纹理时候的过程,如上图

注意在UE4中,UV坐标是不同的,与unity相比是将绿通道反转了。所以使用的Flowmap也会发生变化,要根据引擎进行调整

偏转后的UV坐标去采样右图后得到下面扭曲贴图

2.为什么要使用flowmap?

原因:

类似UV动画,而非顶点动画。换言之,无需对模型顶点进行操作,易实现,运算开销小。

不仅仅是水面,任何和流动相关的效果都可以采用flowmap。

flowmap不仅仅被用于制作一些侵蚀效果或表面的流动效果,还被用于制作流动的天空球中

二、Flowmap shader

1. 借助Shader Graph与desmos理解flowmap

  1. 采样Flow map获取向量场信息
  2. 用向量场信息,使采样贴图时的UV随时间变化
  3. 对同一贴图以半个周期的相位差采集两次,并线性插值,使贴图流动连续

2. 在shader中实现flowmap

  • 目标:根据flowmap上的值,使纹理随时间偏移。
  • 最简单的随时间偏移:UV - time
  • 为什么是相减:
  1. 先来看看 uv+time 的情况
  2. (u,v) + (time,0) :模型上某个点: 随着time增加,采样到的像素越远
  3. 视觉上可以形容为:更远距离的像素偏移向该点,视觉效果和我们直观认识到的运算法则是相反的。
  4. UV值作为向量(u,v),自然也遵循向量的运算法则。但UV偏移时,改变的不是顶点的位置。  

  5. 单方向运动X

    由flow map获取流动方向√

  6. flow map不能直接使用,因为flowmap的范围说[0,1]

    先将flow map上的色值从[0,1]的范围映射到方向向量的范围[-1,1]即乘2减1

从flowmap获取需要的流动方向,再乘Time就可以让某个点去根据flowmap进行流动

调整采样时的UV为: adjust_uv = uv - flowDir * time

在这里我们用FlowSpeed来控制向量场的强度

但随着时间的增加,扭曲程度会越来越大,所以需要一个Fraction函数把时间变成[0,1]的循环 把它变成一个三角波函数

如何实现呢?

我们需要构造两层采样相差半个周期的采样,再对他们进行插值混合

随着时间进行,变形越来越夸张,为了把偏移控制在一定范围内:

frac函数是一个常用的数学函数,主要用于提取浮点数的小数部分。

解决frac产生的跳变,把上面改成:

我们希望的流动:无缝循环

用相位差半个周期的两层采样进行加权混合,使纹理流动一个周期重新开始时的不自然情况被另一层采样覆盖

用flowmap修改法线贴图

三、Flowmap的制作

1. Flowmap Painter

Unity制作的绘制flowmap的工具

注意:

用该工具得到的flowmap为线性空间下的颜色,

不需要gamma矫正,Unity中请取消勾选“□SRGB”

flowmap的烘培和相关设置

 flowmap贴图设置:
1.无压缩或高质量

2.确认色彩空间

导出时注意gamma校正选项、UV匹配

2. Houdini Labs

Houdini Labs是内置在houdini中的一组游戏开发相关的节点,可以在github中搜索sidefx Labs或着直接在houdini中安装得到。

在较早版本的houdini中无法在shelf内找到该工具,你只能通过github下载。在这些未被内置到houdini的版本中,这组工具的名称为gamedev。

1. flowmap相关节点功能

2. flowmap的绘制与烘焙

Houdini目前还没有接触,所以这部分先留着以后再研究

四、作业

效果如下:

FGO 奇点

完整代码

Shader "Shader/Flow Map"
{
    Properties
    {
        _MainTex("Main Texture", 2D)   = "while"{}
        _Color("Tint", Color)         = (1,1,1,1)
        //Flowmap
        _FlowMap("Flow Map", 2D)       = "while"{}
        _FlowSpeed("向量场强度", float) = 0.1
        _TimeSpeed("全局流速", float)   = 1
        [Toggle]_reverse_flow("反转流向", Int) = 0
    }
    SubShader
    {       
        Tags 
        { 
            //开启透明渲染"Queue"="Transparent"
            //注意渲染顺序
            "RenderType" = "Opaque" 
            "IgnoreProject" = "True" 
            "RenderType" = "Opaque"
        }

        Cull Off
        Lighting Off
        ZWrite On

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma Shader_feature_REVESE_FLOW_ON

            #include "UnityCG.cginc"

            struct appdata_t
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            sampler2D _MainTex; 
            float4 _MainTex_ST;
            fixed4 _Color;
            sampler2D _FlowMap;
            float _FlowSpeed;
            float _TimeSpeed;

            v2f vert (appdata_t v)
            {
                v2f o;

                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;
                //o.color = i.color * _Color;

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //从flowmap获取流向
                float3 flowDir = tex2D(_FlowMap, i.uv) * 2.0 - 1.0;

                //FlowSpeed影响向量场强度,值越大,不同位置流速差越明显
                flowDir *= -_FlowSpeed;

                //如果勾选,则反向流转
                #ifdef _REVERSE_FLOW_ON
                       flowDir *= -1;
                #endif

                //构造周期相同,相位相差半个周期的波形函数
                float phase0 = frac(_Time * 0.1 * _TimeSpeed);
                float phase1 = frac(_Time * 0.1 * _TimeSpeed + 0.5);

                //平铺贴图用的uv
                float2 tilling_uv = i.uv * _MainTex_ST.xy + _MainTex_ST.zw;

                //用偏移后的uv对材质进行偏移采样
                half3 tex0 = tex2D(_MainTex, tilling_uv - flowDir.xy * phase0);
                half3 tex1 = tex2D(_MainTex, tilling_uv - flowDir.xy * phase1);

                //构造函数计算波形函数变化的权值,使用MainTex采样值在接近最大偏移时有权值为0,并因此消隐构造较为平滑的循环
                float flowLerp = abs((0.5 - phase0) / 0.5);
                half3 finalColor = lerp(tex0, tex1, flowLerp);

                fixed4 c = float4(finalColor, 1.0) * _Color;

                return c;
            }
            ENDCG
        }
    }
}

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

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

相关文章

Python知识点14---被规定的资源

提前说一点:如果你是专注于Python开发,那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了,而如果你和作者一样只是操作其他技术的Python API那就足够了。 在Python中被规定的东西不止有常识中的那些关键字、构造器等编程语言…

Vue3-Ref Reactive toRef toRefs对比学习、标签ref与组件ref

响应式数据: Ref 作用:定义响应式变量。 语法:let xxx ref(初始值)(里面可以是任何规定内类型、数组等)。 返回值:一个RefImpl的实例对象,简称ref对象或ref,ref对象的value属性是响应式的。 注意点&am…

公网如何访问内网?

公网和内网已经成为我们生活中不可或缺的存在。由于内网的安全性考虑,公网无法直接访问内网资源。如何实现公网访问内网呢?本文将介绍一种名为【天联】的私有通道技术,通过安全加密,保障数据传输的安全性。 【天联】私有通道技术 …

利用Python处理DAX多条件替换

小A:白茶,救命啊~~~ 白茶:什么情况? 小A:是这样的,最近不是临近项目上线嘛,有一大波度量值需要进行类似的调整,一个两个倒没啥,600多个,兄弟,救命…

STM32_FSMC_HAL(介绍)

FSMC(Flexible Static Memory Controller)是STM32微控制器中的一种内存控制器,它允许微控制器与外部存储器接口,如SRAM、NOR Flash、NAND Flash和PSRAM等。FSMC特别适用于需要高速数据交换和大量数据存储的应用场景。 典型应用&a…

06.持久化存储

6.持久化存储 pv: persistent volume 全局的资源 pv,node pvc: persistent volume claim 局部的资源(namespace)pod,rc,svc 6.1:安装nfs服务端(192.168.111.11) yum install nfs-utils.x86_64 -y mkdir /data vim /…

Linux——多线程(二)

在上一篇博客中我们已经介绍到了线程控制以及对应的函数调用接口&#xff0c;接下来要讲的是真正的多线程&#xff0c;线程安全、线程互斥、同步以及锁。 一、多线程 简单写个多线程的创建、等待的代码 #include<iostream> #include<pthread.h> #include<un…

【案例实操】银河麒麟桌面操作系统实例分享,V10SP1重启后网卡错乱解决方法

1.问题现象 8 个网口&#xff0c; 命名从 eth1 开始到 eth8。 目前在系统 grub 里面加了 net.ifnames0 biosdevname0 参数&#xff0c; 然后在 udev 规则中加了一条固定网卡和硬件 pci 设备号的规则文件。 最后在 rc.local 中加了两条重新安装网卡驱动的命令&#xff08; rmmod…

yolov10模块

yolov10模块 1 C2f2 C2fCIB2.1 CIB2.2 RepVGGDW 3 PSA4 SCDown5 v10Detect 论文代码&#xff1a;https://github.com/THU-MIG/yolov10 论文链接&#xff1a;https://arxiv.org/abs/2405.14458 Conv是Conv2dBNSiLU PW是Pointwise Convolution(逐点卷积) DW是Depthwise Convolut…

45页超干PPT:AGV技术详解

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 完整版文件和更多学习资料&#xff0c;请球友到知识星球【智能仓储物流技术研习社】自行下载 AGV&#xff08;Automated Guided Vehicle&#xf…

JVM的垃圾回收机制

目录 GC的工作范围 谁是垃圾 怎么判断&#xff0c;某个对象是否有引用指向捏&#xff1f; &#xff08;1&#xff09;引用计数 缺陷 释放垃圾的策略 &#xff08;1&#xff09;标记清除&#xff08;不实用&#xff09; &#xff08;2&#xff09;复制算法 &#xff08…

公网IP地址如何查询?

公网IP地址是指在互联网中可以被全球范围内的设备访问的IP地址。在网络通信中&#xff0c;公网IP地址扮演着重要的角色&#xff0c;它可以标识设备在互联网中的位置。查询公网IP地址是一种常见的网络管理需求&#xff0c;因为它能够提供网络设备的准确位置信息&#xff0c;方便…

首套真题解析!安徽211难度适中!两门课!

这个系列会分享名校真题。并做详细解析&#xff01;此为24年第一套&#xff01; 今天分享的是22年合肥工业856的信号与系统试题及解析。 小马哥Tips&#xff1a; 本套试卷难度分析&#xff1a;本套试题内容难度中等&#xff0c;里面较多的考察了信号与系统的知识&#xff0c…

[Python]用Qt6和Pillow实现截图小工具

本文章主要讲述的内容是&#xff0c;使用python语言借助PyQt6和Pillow库进行简单截图工具的开发&#xff0c;含义一个简单的范围裁剪和软件界面。 主要解决的问题是&#xff0c;在高DPI显示屏下&#xff0c;坐标点的偏差导致QWidget显示图片不全、剪裁范围偏差问题。 适合有一点…

基于 Redis 实现分布式锁的全过程

前言 这一篇文章拖了有点久&#xff0c;虽然在项目中使用分布式锁的频率比较高&#xff0c;但整理成文章发布出来还是花了一点时间。在一些移动端、用户量大的互联网项目中&#xff0c;经常会使用到 Redis 分布式锁作为控制访问高并发的工具。 一、关于分布式锁 总结&#x…

QT 信号和槽教程,窗体和控件对象之间的沟通一般都使用信号和槽

Qt的信号和槽&#xff08;Signals and Slots&#xff09;机制是一种强大的对象间通信方式&#xff0c;它允许对象在完全解耦的情况下相互通信。以下是关于Qt信号和槽的简明教程&#xff1a; 基本概念 信号&#xff08;Signal&#xff09;&#xff1a;信号是由Qt对象发出的通知…

OpenAI已全面开放自定义GPT以及文件上传等功能

今天&#xff0c;OpenAI兑现了前段时间做出的承诺&#xff1a;免费向所有用户开放GPT-4o。这意味着所有的免费用户都能使用自定义GPT模型、分析图表等其他GPT-4o新功能了。现在ChatGPT界面长这样&#xff1a; 可以看出&#xff0c;免费用户也能使用GPT store中定义好的模型&…

构建智慧监控系统的功能架构,保障安全与便利

智慧监控系统作为现代城市安全管理的重要工具&#xff0c;不仅能够提供有效的安防监控&#xff0c;还能为人们的生活带来更多的便利。本文将探讨智慧监控系统的功能架构&#xff0c;以实现安全和便利的双重目标。 ### 1. 智慧监控系统背景 随着城市化进程的加速&#xff0c;人…

构建高效便捷的家政平台系统——打造优质家政服务的关键

随着人们生活节奏的加快和工作压力的增大&#xff0c;家政服务的需求日益增长。为了满足这一需求&#xff0c;家政平台系统应运而生。本文将探讨家政平台系统的整体架构&#xff0c;以实现高效便捷的家政服务&#xff0c;打造优质家政体验。 ### 1. 家政平台系统背景 随着现代…

语音降噪算法库介绍

一.语音降噪技术方向介绍 软件上进行语音降噪目前主要是两个方向&#xff1a;传统降噪算法和AI降噪算法&#xff0c;他们各有千秋&#xff0c;目前看他们各有千秋&#xff0c;有各自适用场景。 推荐一个不错的人工智能学习网站&#xff0c;通俗易懂&#xff0c;内容全面&#…