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

news/2025/1/11 14:58:08/

庄懂的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、作业:


http://www.ppmy.cn/news/80607.html

相关文章

微前端nuxt3.0方便请求api可封装一个使用哈希算法出key值的http,http封装

http.ts import { hash } from ohash import type { FetchOptions } from ohmyfetch interface httpOptions { source?: string } /**** 获取接口前缀 */ 我这里为不同站点的接口做了区分&#xff0c;主站点为api&#xff0c;demo站点为demoapi function GetPrefixUrl(so…

IMX6ULL裸机篇之DDR3参数配置分析

一. DDR3L 初始化简介 上一篇博文进行了 DDR参数的初始化&#xff0c;通过一个 execl表进行配置&#xff0c;生成脚本文件。文章网址如下&#xff1a; IMX6ULL裸机篇之DDR3初始化_凌雪舞的博客-CSDN博客 本文对 DDR的参数配置进行详细的说明。即对 "Register Configur…

记一次docker中的oracle连接问题

起因是客户登陆时报错TNS-12537 登陆上上服务器后&#xff0c;发现了几个特点。 1、没有oracle用户 2、数据文件的位置和spfile里面写的不一样 3、pmon进程存在&#xff0c;但是父进程ID不是1 4、配置oracle用户及环境变量&#xff0c;但是as sysdba无法登录到数据库 查看…

测试岗位是巨坑,7年测试告诉你千万别入行.....

每次都有人问我软件测试的前景是什么样的&#xff0c;每年也会有人很多人纷纷涌入测试的岗位上&#xff0c;希望自己能够进入阿里、华为等大厂 但是测试岗位真的那么吃香吗&#xff1f;今天我结合从零基础小白到测试开发的成长经历&#xff0c;来说下这个行业的发展前景&#…

【算法】Convert to Base -2 负二进制转换

文章目录 Convert to Base -2 负二进制转换问题描述&#xff1a;分析代码 Convert to Base -2 负二进制转换 问题描述&#xff1a; 给你一个整数 n &#xff0c;以二进制字符串的形式返回该整数的 负二进制&#xff08;base -2&#xff09;表示。 注意&#xff0c;除非字符串…

应用交付流程安全规范

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/130793290 一、平台安全使用规范 平台安全使用规范主要是规定平台层&#xff08;包括主机、Kubernetes集群&#xff09;的用户和文件权限及Kubernetes平台配置和使用规则。 如下所示&#xff1a; 类…

图像滤波概述

什么是图像滤波 1.图像滤波&#xff0c;即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制&#xff0c;是图像预处理中不可缺少的操作&#xff0c;其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。 2.消除图像中的噪声成分叫作图像的平滑化或滤波操…

C++中string的用法

博主简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的人。 博主主页&#xff1a;陈童学哦 所属专栏&#xff1a;CSTL 前言&#xff1a;Hello各位小伙伴们好&#xff01;欢迎来到本专栏CSTL的学习&#xff0c;本专栏旨在帮助大家了解…