庄懂的TA笔记(十七)<特效:屏幕UV + 屏幕扰动>
庄懂的TA笔记(十七)<特效:屏幕UV + 屏幕扰动>
大纲:
目录
庄懂的TA笔记(十七)<特效:屏幕UV + 屏幕扰动>
大纲:
正文:
一、屏幕UV:
二、屏幕扰动:
三、任务委托:
正文:
一、屏幕UV:
1、案例展示:
屏幕UV在过往案例使用中,出现了 镜头畸变,纹理大小不能锁定等问题,这节内容就把屏幕UV的使用全部讲完。
这个效果中是 没有边缘畸变的,到边缘是完完整整的平铺上去的。所以屏幕UV 的重点就在这两个部分。
畸变解决:
纹理大小锁定:
2、实现思路:
主图透贴纹理UV + 屏幕纹理UV流动 = 最终ScreenUV效果;
3、代码实现:
①、面板参数定义:
_MainTex : (RGB : 颜色 A : 透贴 ,2d)="gray"{}
_Opacity :("透明",range(0,1))=0.5
这里屏幕坐标纹的Tillng 和 offset是要用到的,所以需要追加_ST。
_ScreenTex : ("屏幕纹理" , 2d) = "black"{}
②、输出结构:
因为需要用到 主图UV 和 屏幕UV ,所以这里要定义出,uv,和 screenUV.
③、顶点shader输入输出:
float3 posVS = UnityObjectToViewPos(v.vertex).xyz; // 获取顶点位置到摄像机位置的xyz。
o.ScreenUV1 = posVS.xy;//赋值给屏幕UV 。
像素shader: (中间输出测试监测)
float3 var_ScreenTex = tex2D(_ScreenTex,i.ScreenUV1);
return float4(var_ScreenTex,1);
重点:屏幕UV 位置,畸变修正,纹理大小锁定。
取屏幕空间UV位置,取xyz三个轴,
如何理解Vive空间呢?Vive空间相当于以摄像机平面为基准的空间,XY轴对应UV,Z轴对应深度。
但是,正常我们将 XY轴向的UV采样后,会发现贴图在模型表面会有畸变,
如图:
解决方法: 也很简单,直接xy ➗ z 深度 就好了。
o.screenUV = posVS.xy / posVS.z; // VS空间畸变校正
但矫正过后,还会有一个问题,就是你的屏幕UV纹理,相对于你的屏幕Tiling大小是不随距离改变的,正常是模型纹理,会随距离,近大远小的,所以这里我们需要对屏幕UV纹理进行锁定。
如图;
解决方法:得到观察空间的距离,第一个就需要获得模型的原点.
UnityObjectToVivePos float3(0,0,0).z
声明一个orignDist存 模型原点,到 距离摄像机的距离。
float3 orignDist = UnityObjectToVivePos(float3(0,0,0)).z;
然后 在将 屏幕UV * 距离(模型到相机的距离) = 锁定后的屏幕UV.(锁定屏幕UV);
o.screenUV = posVS.xy / posVS.z; // VS空间畸变校正
o.screenUV *= originDist; // 纹理大小按距离锁定
o.screenUV * = orignDist; or o.screenUV = o.screenUV * orignDist(两种方式等价)
综上所属,主要问题就解决了。
如图:
④、屏幕UV滚动:
这里就控制Tiling和offset 流动起来,
ScreenTex_ST. X Y 对应 Tiling的 X Y ;
ScreenTex_ST. Z W 对应 offset的 Z W ;
o.screenUV = o.screenUV * _ScreenTex_ST.X Y - frac(_Time * _ScreenTex_ST.Z W);
(这里 的 + - 都可以用,主要是控制 流动方向的)
o.screenUV=o.screenUV*_ScreenTex_ST.xy - frac(_Time.x * _ScreenTex_ST.zw)启用屏幕纹理ST
如图:
⑤、像素shader:
采样 两张图,两个UV ,主贴图,屏幕空间贴图。
混合透明 = 主图var_MainTex.a * 不透明_Opacity * 屏幕贴图var_ScreenTex;
float3 FinalRGB = var_MainTex.rgb ;
float opacity = var_MainTex.a * _Opacity * var_ScreenTex;
return float4 (FinalRGB * opacity , opacity);
4、核心代码:
重要的就是这一段, (屏幕UV 矫正 和 锁定)
5、屏幕UV 代码示例:
Shader "AP01/L17/ScreenUV" {Properties {_MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}_Opacity ("透明度", range(0, 1)) = 0.5_ScreenTex ("屏幕纹理", 2d) = "black" {}}SubShader {Tags {"Queue"="Transparent" // 调整渲染顺序"RenderType"="Transparent" // 对应改为Cutout"ForceNoShadowCasting"="True" // 关闭阴影投射"IgnoreProjector"="True" // 不响应投射器}Pass {Name "FORWARD"Tags {"LightMode"="ForwardBase"}Blend One OneMinusSrcAlpha // 混合方式CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#pragma multi_compile_fwdbase_fullshadows#pragma target 3.0// 输入参数uniform sampler2D _MainTex;uniform half _Opacity;uniform sampler2D _ScreenTex; uniform float4 _ScreenTex_ST;// 输入结构struct VertexInput {float4 vertex : POSITION; // 顶点位置 OSfloat2 uv : TEXCOORD0; // UV信息};// 输出结构struct VertexOutput {float4 pos : SV_POSITION; // 顶点位置 CSfloat2 uv : TEXCOORD0; // UV信息float2 screenUV : TEXCOORD1; // 屏幕UV};// 输入结构>>>顶点Shader>>>输出结构VertexOutput vert (VertexInput v) {VertexOutput o = (VertexOutput)0;o.pos = UnityObjectToClipPos(v.vertex); // 顶点位置 OS>CSo.uv = v.uv; // UV信息float3 posVS = UnityObjectToViewPos(v.vertex).xyz; // 顶点位置 OS>VSfloat originDist = UnityObjectToViewPos(float3(0.0, 0.0, 0.0)).z; // 原点位置 OS>VSo.screenUV = posVS.xy / posVS.z; // VS空间畸变校正o.screenUV *= originDist; // 纹理大小按距离锁定o.screenUV = o.screenUV * _ScreenTex_ST.xy - frac(_Time.x * _ScreenTex_ST.zw); // 启用屏幕纹理STreturn o;}// 输出结构>>>像素half4 frag(VertexOutput i) : COLOR {half4 var_MainTex = tex2D(_MainTex, i.uv); // 采样 基本纹理 RGB颜色 A透贴half var_ScreenTex = tex2D(_ScreenTex, i.screenUV).r; // 采样 屏幕纹理// FinalRGB 不透明度half3 finalRGB = var_MainTex.rgb;half opacity = var_MainTex.a * _Opacity * var_ScreenTex;// 返回值return half4(finalRGB * opacity, opacity);}ENDCG}}
}
二、屏幕扰动:
1、案例展示:
2、实现思路:
屏幕扰动(玻璃效果)
背景信息获取:
MainTex 红或蓝通道扭曲:
①、面板参数定义:
_MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}
_Opacity ("不透明度", range(0, 1)) = 0.5
_WarpMidVal ("扰动中间值", range(0, 1)) = 0.5
_WarpInt ("扰动强度", range(0, 5)) = 1
这里的中间值 扭曲度,因为我们用的是主图自带的通道中的信息,RGB中不同通道的像素可能偏亮,可能偏暗,会影响扭曲的强弱, 因为不像 法线的中间值是正常的0.5,偏移扭曲的正常的数值,所以这里声明了一个 用于矫正的 "扰动中间值"(_WarpMidVal)
②、追加GrabPass 获取扭曲背景_BGTex==背景纹理采样坐标(现成黑盒):
产生这张图:
获取背景纹理,他的含义为:渲染主体物前,将背景存成一张图,名字就叫 _BGTex.
实际上就是,扰动前,把背景图存起来,然后再用屏幕坐标UV把 背景图(_BGTex)贴回去。
GrabPass {
"_BGTex"
}
获取这张图:
uniform sampler2D _BGTex; // 拿到背景纹理
输出结构中 : (VertexOutput)
float4 grabPos : TEXCOORD1; // 背景纹理采样坐标(4维的)
顶点shader输入输出结构中 :
o.grabPos = ComputeGrabScreenPos(o.pos); // 背景纹理采样坐标
像素shader中采样:
half3 var_BGTex = tex2Dproj(_BGTex, i.grabPos).rgb;// 采样背景
③、像素shader下 采样和计算:
获取主贴图 通道信息作为源,来扭曲背景图(grabPos)采样坐标XY;
// 采样 基本纹理 RGB颜色 A透贴
half4 var_MainTex = tex2D(_MainTex, i.uv);
<这里用主图的B蓝通道,减去中间值,减去是什么意思呢,相当于有正有负,在乘强度(_WarpInt) 在乘 透明度(_Opacity),就得到透明的扰动效果>。
// 扰动背景纹理采样UV
i.grabPos.xy+=(var_MainTex.b - _WarpMidVal) * _WarpInt * _Opacity;
// 采样背景
half3 var_BGTex = tex2Dproj(_BGTex, i.grabPos).rgb;
用_Opacity控制 1 到 主图透明 的插值,并乘以 透明的背景信息,得到 带透贴的扰动主图。
// FinalRGB 不透明度
half3 finalRGB = lerp(1.0, var_MainTex.rgb, _Opacity) * var_BGTex;
half opacity = var_MainTex.a;
// 返回值
return half4(finalRGB * opacity, opacity);
3、代码实现:
4、核心代码
5、屏幕扰动 代码示例:
Shader "AP01/L17/ScreenWarp" {Properties {_MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}_Opacity ("不透明度", range(0, 1)) = 0.5_WarpMidVal ("扰动中间值", range(0, 1)) = 0.5_WarpInt ("扰动强度", range(0, 5)) = 1}SubShader {Tags {"Queue"="Transparent" // 调整渲染顺序"RenderType"="Transparent" // 对应改为Cutout"ForceNoShadowCasting"="True" // 关闭阴影投射"IgnoreProjector"="True" // 不响应投射器}// 获取背景纹理GrabPass {"_BGTex"}// Forward PassPass {Name "FORWARD"Tags {"LightMode"="ForwardBase"}Blend One OneMinusSrcAlpha // 混合方式CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#pragma multi_compile_fwdbase_fullshadows#pragma target 3.0// 输入参数uniform sampler2D _MainTex;uniform half _Opacity;uniform half _WarpMidVal;uniform half _WarpInt;uniform sampler2D _BGTex; // 拿到背景纹理// 输入结构struct VertexInput {float4 vertex : POSITION; // 顶点位置 总是必要float2 uv : TEXCOORD0; // UV信息 采样贴图用};// 输出结构struct VertexOutput {float4 pos : SV_POSITION; // 顶点位置 总是必要float2 uv : TEXCOORD0; // UV信息 采样贴图用float4 grabPos : TEXCOORD1; // 背景纹理采样坐标};// 输入结构>>>顶点Shader>>>输出结构VertexOutput vert (VertexInput v) {VertexOutput o = (VertexOutput)0;o.pos = UnityObjectToClipPos( v.vertex); // 顶点位置 OS>CSo.uv = v.uv; // UV信息o.grabPos = ComputeGrabScreenPos(o.pos); // 背景纹理采样坐标return o;}// 输出结构>>>像素half4 frag(VertexOutput i) : COLOR {// 采样 基本纹理 RGB颜色 A透贴half4 var_MainTex = tex2D(_MainTex, i.uv);// 扰动背景纹理采样UVi.grabPos.xy += (var_MainTex.b - _WarpMidVal) * _WarpInt * _Opacity;// 采样背景half3 var_BGTex = tex2Dproj(_BGTex, i.grabPos).rgb;// FinalRGB 不透明度half3 finalRGB = lerp(1.0, var_MainTex.rgb, _Opacity) * var_BGTex;half opacity = var_MainTex.a;// 返回值return half4(finalRGB * opacity, opacity);}ENDCG}}
}
三、任务委托:
1、作业:
相关文章:

庄懂的TA笔记(十七)<特效:屏幕UV + 屏幕扰动>
庄懂的TA笔记(十七)<特效:屏幕UV 屏幕扰动> 大纲: 目录 庄懂的TA笔记(十七)<特效:屏幕UV 屏幕扰动> 大纲: 正文: 一…...

手写简易RPC框架
目录 简介 服务提供者 服务注册:注册中心 HttpServerHandler处理远程调用请求 consumer服务消费端 简介 RPC(Remote Procedure Call)——远程过程调用,它是一种通过网络从远程计算机程序上请求服务, 而不需要了解…...

基于孪生网络的目标跟踪
一、目标跟踪 目标跟踪是计算机视觉领域研究的一个热点问题,其利用视频或图像序列的上下文信息,对目标的外观和运动信息进行建模,从而对目标运动状态进行预测并标定目标的位置。具体而言,视觉目标(单目标)…...

苏州狮山广场能耗管理系统
摘要:随着社会生活水平的提高,经济的繁荣发展,人们对能源的需求逐渐增长,由此带来的能源危机日益严重。商场如何实时的了解、分析和控制商场的能源消耗已成为需要解决的迫在眉睫的难题。传统的能源消耗智能以月/季度/年为周期进行…...

Jupyter Notebook 10个提升体验的高级技巧
Jupyter 笔记本是数据科学家和分析师用于交互式计算、数据可视化和协作的工具。Jupyter 笔记本的基本功能大家都已经很熟悉了,但还有一些鲜为人知的技巧可以大大提高生产力和效率。在这篇文章中,我将介绍10个可以提升体验的高级技巧。 改变注释的颜色 颜…...
CF 751 --B. Divine Array
Black is gifted with a Divine array a consisting of n (1≤n≤2000) integers. Each position in a has an initial value. After shouting a curse over the array, it becomes angry and starts an unstoppable transformation. The transformation consists of infinite…...

Springcloud1--->Eureka注册中心
目录 Eureka原理Eureka入门案例编写EurekaServer将user-service注册到Eureka消费者从Eureka获取服务 Eureka详解基础架构高可用的Eureka Server失效剔除和自我保护 Eureka原理 Eureka:就是服务注册中心(可以是一个集群),对外暴露自…...

面试阿里、字节全都一面挂,被面试官说我的水平还不如应届生
测试员可以先在大厂镀金,以后去中小厂毫无压力,基本不会被卡,事实果真如此吗?但是在我身上却是给了我很大一巴掌... 所谓大厂镀金只是不卡简历而已,如果面试答得稀烂,人家根本不会要你。况且要不是大厂出来…...

JAVA开发(记一次删除完全相同pgSQL数据库记录只保留一条)
进行数据管理时,无效数据可能会对生产力和决策质量造成严重的影响。如何发现和处理无效数据变得愈发重要。一起来唠唠你会如何处理无效数据吧~ 方向一:介绍无效数据的概念 最近遇到了pg数据库表中的大量数据重复了,需要删除其中的一条。一条…...

音视频八股文(7)-- 音频aac adts三层结构
AAC介绍 AAC(Advanced Audio Coding)是一种现代的音频编码技术,用于数字音频的传输和存储领域。AAC是MPEG-2和MPEG-4标准中的一部分,可提供更高质量的音频数据,并且相比于MP3等旧有音频格式,AAC需要更少的…...

Docker代码环境打包进阶 - DockerHub分享镜像
1. Docker Hub介绍 Docker Hub是一个广泛使用的容器镜像注册中心,为开发人员提供了方便的平台来存储、共享和分发Docker容器镜像。它支持版本控制、访问控制和自动化构建,并提供了丰富的公共镜像库,方便开发人员快速获取和使用各种开源应用和…...
SQL进阶-having子句的力量
SQL进阶-having子句的力量 having子句是理解SQL面向集合这一本质的关键。 在以前的SQL标准里面,having子句必须和group by子句一起使用,但是按照现在的SQL标准,having子句是可以单独使用的 可以与case 表达式或者自连接等结合使用。表不是文件…...

Electron 如何创建模态窗口?
目录 前言一、模态窗口1.Web页面模态框2.Electron中的模态窗口3.区分父子窗口与模态窗口 二、实际案例使用总结 前言 模态框是一种常用的交互元素,无论是在 Web 网站、桌面应用还是移动 APP 中,都有其应用场景。模态框指的是一种弹出窗口,它…...

诺贝尔化学奖:酶分子“定向进化”
2018年,诺贝尔化学奖迎来了历史上第五位女性得主——加州理工学院的Frances H. Arnold教授,以表彰她在“酶的定向进化”这一领域的贡献。 1、“酶的定向进化”到底是什么? 这里有三个点,“酶”、“进化”还有“定向”:…...
Centos8下源码编译安装运行Primihub
参考文献 PrimiHub 本地编译启动How to install Bazel on CentOS 8 Linux or Redhat 8/7 编译启动步骤 由于历史原因,服务器是Centos8操作系统,所以源码编译异常的麻烦。特此记录如下。 采用源码编译方式可以在一步步的运行过程中对整个流程进行深刻…...
嘉兴桐乡考证培训-23年教资认定注意事项你知道吗?
又到了新的一年了,去年错过认定的同学们可以竖起耳朵啦~ 每年认定机会有两次,大部分省份一般上半年下半年各一次。 问:在校生可以认定么? 答:可以,但有年级限制:本科生大四最后一学期…...

oracle客户端的安装教程
文章目录 一、安装前的准备工作 1.1、百度网盘安装包的连接 1.2、百度网盘oracle11g软件包 二、oracle数据库客户端的安装与数据的准备 安装步骤 前言 本文主要讲解oracle客户端的安装与简单使用过程 一、安装前的准备工作 1.1、百度网盘安装包的连接 客户端的软件包 …...

python 文件操作 , 异常处理 , 模块和包
文件操作 1.写数据 # open(name, mode) # name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。 # mode:设置打开文件的模式(访问模式):只读、写入、追加等。 #1.打开文件---通道建立--申请资源 # w 模式会清空之前的内…...
AIGC技术研究与应用 ---- 下一代人工智能:新范式!新生产力!(1-简介)
文章大纲 AI GC简介决策式/分析式AI(Discriminant/Analytical AI)和生成式AI (Generative AI)参考文献与学习路径模型进化券商研报陆奇演讲AI GC 《我,机器人》中所演绎的一样,主角曾与机器人展开了激烈的辩论,面对“机器人能写出交响乐吗?”“机器人能把画布变成美丽…...

Flask restful分页接口实现
1.先定义一个工作信息表: 指定一些相关的字段:工作名称、年限、级别等 class Work(db.Model):__tablename__ = workid = db.Column(db.Integer, primary_key=True)workName = db.Column(db.String(5),nullable=False)year = db.Column(db.String(20), nullable=False)level = …...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...