庄懂的TA笔记(十七)<特效:屏幕UV + 屏幕扰动>

2023-10-08 04:40

本文主要是介绍庄懂的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轴对应UVZ轴对应深度

但是,正常我们将 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滚动:

这里就控制Tilingoffset 流动起来,

ScreenTex_ST. X Y 对应 TilingX Y ;

ScreenTex_ST. Z W 对应 offsetZ 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 + 屏幕扰动>的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/162756

相关文章

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

查看提交历史 —— Git 学习笔记 11

查看提交历史 查看提交历史 不带任何选项的git log-p选项--stat 选项--pretty=oneline选项--pretty=format选项git log常用选项列表参考资料 在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的 工具是 git log 命令。 接下来的例子会用一个用于演示的 simplegit

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

忽略某些文件 —— Git 学习笔记 05

忽略某些文件 忽略某些文件 通过.gitignore文件其他规则源如何选择规则源参考资料 对于某些文件,我们不希望把它们纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常它们都是些自动生成的文件,比如日志文件、编译过程中创建的临时文件等。 通过.gitignore文件 假设我们要忽略 lib.a 文件,那我们可以在 lib.a 所在目录下创建一个名为 .gi

取得 Git 仓库 —— Git 学习笔记 04

取得 Git 仓库 —— Git 学习笔记 04 我认为, Git 的学习分为两大块:一是工作区、索引、本地版本库之间的交互;二是本地版本库和远程版本库之间的交互。第一块是基础,第二块是难点。 下面,我们就围绕着第一部分内容来学习,先不考虑远程仓库,只考虑本地仓库。 怎样取得项目的 Git 仓库? 有两种取得 Git 项目仓库的方法。第一种是在本地创建一个新的仓库,第二种是把其他地方的某个

Git 的特点—— Git 学习笔记 02

文章目录 Git 简史Git 的特点直接记录快照,而非差异比较近乎所有操作都是本地执行保证完整性一般只添加数据 参考资料 Git 简史 众所周知,Linux 内核开源项目有着为数众多的参与者。这么多人在世界各地为 Linux 编写代码,那Linux 的代码是如何管理的呢?事实是在 2002 年以前,世界各地的开发者把源代码通过 diff 的方式发给 Linus,然后由 Linus