【TA 100】Flow Map实现水体流动效果

news2025/3/1 0:44:18

最近刚好学到Shader Graph水体流动,看下其他实现方式记录下

1 什么是flow map

1 什么是Flow map?
flowmap的实质:一张记录了2D向量信息的纹理Flow map上的颜色(通常为RG通道) 记录该处向量场的方向,让模型上某一点表现出定量流动的特征。通过在shader中偏移uv再对纹理进行采样,来模拟流动效果

在这里插入图片描述

2 纹理映射,左边是UV坐标值,右边是采样结果

在这里插入图片描述

UV使用flow map偏移出现不同效果

在这里插入图片描述

为什么要使用flowmap?
类似UV动画,而非顶点动画。换言之,无需对模型顶点进行操作,易实现运算开销小。
不仅仅是水面,任何和流动相关的效果都可以采用flowmap.

flowmap的原理:通过所带有的向量场信息对uv进行了一个偏移,来干扰我们采样时候的这个过程。如图可以看到,经过flowmap发生偏移后,让原本正常的采样变成了一个扭曲的效果

我们需要更好的运动方向,正确的方法是从flowMap获取流动方向,但是,flow map不能直接使用,需要将flow map上的色值从[0,1]的范围映射到方向向量的范围[-1.1].在这里插入图片描述

在这里插入图片描述

2 flow map Shader

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

这里用到了一个函数模拟网站
https://www.desmos.com/calculator?lang=zh-CN

最简单的随时]间偏移?
time
为什么是相减?
先来看看 uv+time 的情况uv) + (time.0) :模型上某个点: 随着time增加,采样到的像素越远
视觉上可以形容为: 更远距离的像素偏移向该点,视觉效果和我们直观认识到的运算法则是相反的.
UV值作为向量 (u,v) ,自然也遵循向量的运算法则.但UV偏移时,改变的不是顶点的位置。
在这里插入图片描述
请添加图片描述

在这里插入图片描述

https://teckartist.com/?page_id=107 点击下载流形图绘制工具
在这里插入图片描述

请添加图片描述
随着时间进行,变形越来越夸张,需要把偏移控制在一定范围内实现无缝循环
在这里插入图片描述

依据Flowmap的原理,我们想要做出流动效果,就需要uv随时间进行周期性偏移
既然是周期性偏移,那么时间必须有个阀值 周期有阀值人们第一想到是frac()函数
但frac()函数有个问题,那就是周期的有断层
在这里插入图片描述人们希望0.99循环 到1的断层去掉 这时候有个聪明人想到了加权平均.用两条有周期有规律变换的线 蓝紫两线的加权不断变换使断层效果消失 x=0.5时蓝线权重1 紫线权重0 x=1时蓝线权重0紫线权重1
在这里插入图片描述
那么 x在0~1周期 y在010线性波动的怎么做呢? 有人给公式了
有人会想到 sin和cos +一些变化代替上面的公式 这并不好用因为输入是弧度π是无理数. 你无法准确控制sin和cos的周期 用/3.1415926 这种形式运算也废GPU指令 时间拉长就会有越来越大误差.
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
请添加图片描述

3 Shader实现

frac函数的作用
在这里插入图片描述

Shader "MyShader/Water"
{
    Properties
    {
        // basecolor
        _MainTex ("Texture", 2D) = "white" {}
        //混色
        _Color("Tint", Color) = (1,1,1,0.5)
        //水体法线
        _MainTex ("Texture", 2D) = "white" {}
        _FlowMap("FlowMap", 2D) = "white" {}
        //向量场强度
        _FlowSpeed("intensity", float) = 0.1
        //采样速度
        _TimeSpeed("speed", float)= 1
        //创建开关
        [Toggle]_reverse_flow("reverse", Int) = 0
    }
    SubShader
    {
        Tags { 
                "RenderType"="Opaque"
                "IgnoreProjector" = "True"
        }
        Cull Off
        Lighting Off
        ZWrite On
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma shader_feature _REVERSE_FLOW_ON

            #include "UnityCG.cginc"

            struct a2v
            {
                float4 pos : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 pos : SV_POSITION;
            };

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

            v2f vert (a2v v)
            {
                v2f o;
                //顶点坐标
                o.pos = UnityObjectToClipPos(v.pos);
                //顶点UV
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //0~1 *2-1 得到 -1~1 方向
                fixed4 flowDir = tex2D(_FlowMap, i.uv) * 2.0 - 1.0;
                //强度修正
                flowDir *= _FlowSpeed;
                //正负修正
                #ifdef _REVERSE_FLOW_ON
                    flowDir *= -1;
                #endif

                //两个0~1循环 计时
                float phase0 = frac(_Time * 0.1 * _TimeSpeed);
                float phase1 = frac(_Time * 0.1 * _TimeSpeed + 0.5);

                float2 tiling_uv = i.uv * _MainTex_ST.xy +   _MainTex_ST.zw;

                half3 tex0 = tex2D(_MainTex, tiling_uv + flowDir.xy * phase0);
                half3 tex1 = tex2D(_MainTex, tiling_uv + flowDir.xy * phase1);

                float flowLerp = abs((0.5 - phase0) / 0.5);
                half3 finalColor = lerp(tex0, tex1, flowLerp);
                return float4(finalColor, 1.0) * _Color;
            }
            ENDCG
        }
    }
} 

想试试加上NormalMap视频里代码不全,用到了TBN向量计算世界空间法线,后续补。

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

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

相关文章

Python接口自动化—接口测试用例和接口测试报告模板

简介 当今社会在测试领域,接口测试已经越来越多的被提及,被重视,而且现在好多招聘信息要对接口测试提出要求。区别于传统意义上的系统级别测试,很多测试人员在接触到接口测试的时候,也许对测试执行还可以比较顺利的上…

vue高频面试题(一)

大厂面试题分享 面试题库 前后端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 web前端面试题库 VS java后端面试题库大全 VUE Vue2和3对比 脚手架创建项目 之前有个国企,问到了怎么用脚手架创建vue项…

真空热压烧结炉JZM-1200技术参数一览表

真空热压烧结炉是将真空、气氛、热压成型、高温烧结结合在一起设备,适用于粉末冶金、功能陶瓷等新材料的高温热成型。如应用于透明陶瓷、工业陶瓷等金属以及由难容金属组成的合金材料的真空烧结以及陶瓷材料碳化硅和氮化硅的高温烧结,也可用于粉末和压坯…

2. 量化多因子数据清洗——去极值、标准化、正交化、中性化

一、去极值 1. MAD MAD(mean absolute deviation)又称为绝对值差中位数法,是一种先需计算所有因子与平均值之间的距离总和来检测离群值的方法. def extreme_MAD(rawdata, n): median rawdata.quantile(0.5) # 找出中位数 new_median (abs(…

Mybatais-plus超详细教程

文章目录 前言什么是Mybatis-plus特性引入依赖配置日志Service CRUD 接口SaveSaveOrUpdateRemoveUpdateGetListPageCount Chainqueryupdate Mapper CRUD 接口InsertDeleteUpdateSelect 赠送 前言 在学习Mybatis-plus之前,这里默认大家都已经对mybatis使用有了一定的…

召回评价指标NDCG、MAP

【MAP】 1、AP A P ∑ i 1 n r e l ( i ) p i AP \sum_{i1}^{n}\frac{rel(i)}{p_i} APi1∑n​pi​rel(i)​ 其中 n 表示候选序列长度, p i p_i pi​表示第 i 个 item 的位置 本质是对每个位置item的分数加一个基于位置的筛选.简单粗暴,直接除以位置…

NeRF与三维重建专栏(三)nerf_pl源码部分解读与colmap、cuda算子使用

前言 上一章中我们介绍了NeRF原理、传统体渲染方法以及两者之间的联系,本章中我们将讲解colmap的安装以及使用,部分nerf_pl源码,同时在开发过程中,由于部分操作python/torch不支持,我们需要自己造轮子,且在…

37 KVM管理设备-管理设备直通

文章目录 37 KVM管理设备-管理设备直通37.1 PCI直通37.2 SR-IOV直通37.2.1 概述37.2.2 操作方法37.2.2.1 开启网卡的SR-IOV模式37.2.2.2 获取PF和VF的PCI BDF信息37.2.2.3 识别和管理PF/VF对应关系37.2.2.4 挂载SR-IOV网卡到虚拟机中 37.2.3 HPRE加速器SR-IOV直通 37 KVM管理设…

IOS上架流程详解,包含审核避坑指南!

准备 开发者账号完工的项目 上架步骤 一、创建App ID二、创建证书请求文件 (CSR文件)三、创建发布证书 (CER)四、创建Provisioning Profiles配置文件 (PP文件)五、在App Store创建应用六、打包上架 一、…

又一运维利器:资源监控微应用

过去几个月,优维在新的资源监控微应用相关能力的研发上投入大量的时间与精力。 上周三,优维专门召开了一场资源监控微应用发布会,介绍了优维的监控微应用的功能亮点和后续规划。 下面就跟着鹿小U一起来具体了解一下。 01 过去&#xff0c…

需求不完备测试解决方案——分布式微服务架构测试实践

1痛点和研究背景 目前随着分布式核心下移和小型机下线的趋势,主流系统架构已逐步演变为CCETDSQL。而在这一演进过程中也陆续暴露出来一些痛点难点问题,需要我们着力解决。为此,我们聚焦于分布式架构下需求、架构、数据这三个方面的痛点问题探…

【Linux驱动】VScode 环境简单配置

在开始编写驱动之前,我们需要保证良好的编码环境,这里编写代码所使用的编辑器是VScode,如果进行环境配置,可能会提示很多错误,比如头文件找不到、内核函数的定义无法跳转等等。 VScode 在这里只作为编辑器使用&#x…

Springboot配置Yml多环境

文章目录 学习链接前言pom.xmlapplication.ymlapplication-dev.yml 开发环境配置application-prod.yml 线上环境配置logback.xml 日志配置 学习链接 easypan Spring Boot手把手教学(2):使用yml多环境配置和创建多环境profile打包 springboot 配置多环境使用yml配置…

自动化测试介绍和分类,看这一篇就够了

自动化测试介绍及分类 什么是自动化测试? 自动化测试是软件测试活动中一个重要的分支和组成部分,即利用工具或脚本达到测试目的,没有人工或者极少人工参与的软件测试活动称为自动化测试. 自动化测试的优势有哪些? 方便进行回归测试,当软件的版本发布比较频繁的时候,自动化…

平台工程是 DevOps 的未来

Gartner 预测到 2026 年时,将有 80% 的软件工程组织会建立平台团队 DevOps 与平台工程 DevOps 是一种文化和理念。平台工程,是我们实现**“谁构建、谁运行”**的唯一方式。这是 DevOps 的核心初衷,也是后来企业级规模和云原生时代的实现基础…

游泳健身馆预约小程序开发 助力门店拓客引流

暑假快要到了,很多游泳健身馆都想方设法来招揽顾客,其实无论是派发传单还是媒体投放,都不如开发一款游泳健身类预约小程序来的好。因为有了健身游泳小程序系统不仅能够起到很好的推广宣传效果,对于日后的经营发展也有诸多好处。 …

javaEE在2023年5月21知识复盘(一)

今天讲述了doget()、doPost()方法,介绍了里面参数req,resp的一些实用方法 getParameter()获取请求参数 getParameterValues() 返回参数数组 【post方式】 设置编码格式 req-> setCharacterEncoding() resp->SetContent-Type(“text/html;charsetutf-8”) 获取…

SpringBoot + minio实现文件切片极速上传技术(敢说全网整合完整度前三)

一. 概述 提示:请不要多个博客来回跳着看,此文章之详细绝无仅有,融合多家之长,如果遇见报错,请仔细捋一遍文章,不要忽略!我在写的时候因为许多文章不全面,来回跳遇见许多坑&#xf…

Java 集合,你肯定也会被问到这些

作为一位小菜 ”一面面试官“,面试过程中,我肯定会问 Java 集合的内容,同时作为求职者,也肯定会被问到集合,所以整理下 Java 集合面试题 说说常见的集合有哪些吧? HashMap说一下,其中的Key需要重…

傻子都能学会的LNMP部署

LNMP 一、安装 Nginx 服务1、安装依赖包2、创建运行用户3、编译安装4、优化路径5、添加 Nginx 系统服务 二、安装 MySQL 服务】1、安装Mysql环境依赖包2、创建运行用户3、编译安装4、修改mysql 配置文件5、更改mysql安装目录和配置文件的属主属组6、设置路径环境变量7、初始化数…