UV坐标应用范例——计算屏幕坐标作为UV

news2024/10/7 16:17:11

迷幻角色背景

大家好,我是阿赵。
之前介绍过了经典的Shader写法,物体顶点坐标在顶点程序转换到裁剪空间,然后在片段程序里面通过模型的UV进行贴图采样,然后把颜色显示在模型上面。
之前也介绍过经典的顶点程序应用,树木的生长。通过特定的信息,控制顶点的偏移,模拟出树干树枝生长的效果。
这次带来一个我觉得比较经典的UV坐标控制例子。
在这里插入图片描述

一、例子说明

在做这个例子之前,先来考虑一个问题。我们采样模型的贴图,是不是必须使用模型的UV信息?
答案肯定是否的。
我之前在很多例子里面已经用过MatCap效果,采样MatCap就并不是用模型的UV坐标,而是把物体的法线方向转到观察空间,然后再转换到[0,1]的范围,作为采样MatCap贴图的UV信息,可以看代码回顾一下:

float2 GetMatCapUV(float3 objNormal)
	{
float3 normalWorld = mul(unity_ObjectToWorld, objNormal);
float3 normalView = mul(UNITY_MATRIX_IT_MV, normalWorld);
return normalView.xy*0.5+0.5;
}

在这次这个例子里面,我做了一个使用顶点坐标转屏幕空间坐标的操作,使用这个屏幕坐标作为UV来采样贴图。这样得到的效果,模型上的贴图会一直正面朝着屏幕,不会因为模型的旋转或者摄像机的旋转而导致贴图的方向发生变化。模型的顶点范围,只会影响到贴图显示的范围大小。
为了让这个例子看起来更有意思,所以我使用了2个视频作为贴图,所以我先会说一下在Unity里面怎样使用AVProVideo插件播放视频。

二、详细做法说明

1、AVProVideo播放视频

1.导入AVProVideo

在这里插入图片描述

先购买插件,然后导入项目,会看到有一个AVProVideo文件夹,里面会有Demo,想深入了解的话可以去看看各种demo的应用。我这个例子用的不是很复杂,只是单纯的用来播放视频而已,所以那些360播放、VR播放的功能,就不去管了。

2.创建播放器

在这里插入图片描述

导入插件之后,在创建物体对象的地方就可以创建MediaPlayer,在场景里面创建MediaPlayer。

3.指定播放的视频

在这里插入图片描述

选择MediaPlayer,可以看到选项。资源路径里面可以指定播放视频的地址。然后可以设置自动打开、自动播放、循环等。

4.渲染到指定的材质球

在这里插入图片描述

添加一个ApplyToMaterial的组件,可以把指定的MediaPlayer渲染的视频,以RenderTexture的形式传入指定的材质球。

5.为例子准备的2个视频

(1)背景视频

这个背景是我自己用AE做出来的一个循环背景,如果有人有兴趣,可以提出来,我下次再告诉大家怎样做。
在这里插入图片描述

(2)角色身上的视频

这个是AVProVideo插件的demo自带的视频,本来是一个可以贴到球体上的循环视频,我觉得效果不错,就直接拿来做例子了。
在这里插入图片描述

2、制作背景材质

背景其实就是是一个面片,但由于没有拿模型的UV坐标作为采样,而是拿了顶点坐标转屏幕坐标作为UV来采样,所以不管怎样旋转面片,显示的画面都会是正对着我们的
在这里插入图片描述
在这里插入图片描述

关键的计算步骤是:

1.顶点程序

o.screen_pos = ComputeScreenPos(o.vertex);

其中ComputeScreenPos函数是UnityCG.cginc内置的,通过这个方法获取到的屏幕坐标的取值范围已经是[0,1],比自己计算方便。

inline float4 ComputeScreenPos (float4 pos)
{
    float4 o = pos * 0.5f;
    o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w;
    o.zw = pos.zw;
    
    return o;
}

2.片段程序

//用透视除法,将裁剪空间坐标转换到NDC空间坐标

			float2 screenUV = i.screen_pos.xy / (i.screen_pos.w + 0.000001);
			float aspect = _ScreenParams.x / _ScreenParams.y;
			float aspectx = aspect * _scale.x;
			screenUV.x *= aspectx;
			screenUV.x += (1 - aspectx) / 2;
			//判断屏幕UV是否左上角是0,是否需要上下翻转V坐标。
			//由于例子用的是视频插件生成的RenderTexture,没有Repeat,所以不能直接UV坐标乘以-1,改为用1-V坐标
			if(_ProjectionParams.x < 0)
			{
				screenUV.y = 1 - screenUV.y;
			}
			//用屏幕UV采样贴图,得到颜色1
			half4 col = tex2D(_MainTex, screenUV);

这里的重点是用透视除法求NDC空间的坐标。然后用_ScreenParams.x / _ScreenParams.y;求出屏幕的长宽比例,进行偏移,让画面可以在屏幕中间居中。
不过如果单纯是这样计算出UV然后进行采样,会发现画面是上下颠倒的,所以还要根据_ProjectionParams.x判断屏幕UV是否左上角是0,是否需要上下翻转V坐标。
最后就可以把计算出来的UV坐标来采样贴图了。

3、角色材质制作

角色的材质是在背景材质上做了加工。
这里分别用2套UV对角色模型进行了采样,一套是正常的模型UV、另外一套是顶点坐标转屏幕坐标(和背景的计算方式一样)
两套UV都是采样传进去的视频作为贴图,具体的效果如下:
在这里插入图片描述
在这里插入图片描述

接下来要做的事情就非常简单了,我很喜欢用一张噪声图,把它自身的UV平铺数值改成0,0,然后用一个_Time.y来滚动UV坐标,就能采样噪声图的单个像素,做出黑白灰闪动的效果:

float noiseUV = i.uv*_noiseMap_ST.xy + _noiseMap_ST.zw;
noiseUV.x += _Time.y*_speed;
float4 noiseCol = tex2D(_noiseMap, noiseUV);
float noiseVal = step(0.5, noiseCol.r);

在这里插入图片描述
在这里插入图片描述

最后,对黑白灰的效果做step,让它只会出现黑白,然后用来混合刚才两套UV的采样结果,就做出了2种效果之间的闪烁变化了。
float4 finalCol = col * noiseVal + col2 * (1 - noiseVal);

三、完整Shader

Shader "azhao/CenterImgRole"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
		_scale("Scale",Vector) = (1,1,1,1)
		_noiseMap("Noise",2D) = "black"{}
		_speed("Speed",float) = 1
	}
		SubShader
		{
			Tags { "RenderType" = "Opaque" }
			LOD 100

			Pass
			{
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag

				#include "UnityCG.cginc"

				struct appdata
				{
					float4 vertex : POSITION;
					float2 uv : TEXCOORD0;
				};

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

				sampler2D _MainTex;
				float4 _MainTex_ST;
				float4 _scale;
				float _speed;
				sampler2D _noiseMap;
				float4 _noiseMap_ST;
				v2f vert(appdata v)
				{
					v2f o;
					o.vertex = UnityObjectToClipPos(v.vertex);
					o.uv = TRANSFORM_TEX(v.uv, _MainTex);
					//获取顶点对应的屏幕空间坐标
					o.screen_pos = ComputeScreenPos(o.vertex);
					return o;
				}

				half4 frag(v2f i) : SV_Target
				{
					//用透视除法,将裁剪空间坐标转换到NDC空间坐标
					float2 screenUV = i.screen_pos.xy / (i.screen_pos.w + 0.000001);
					float aspect = _ScreenParams.x / _ScreenParams.y;
					float aspectx = aspect * _scale.x;
					screenUV.x *= aspectx;
					screenUV.x += (1 - aspectx) / 2;
					//判断屏幕UV是否左上角是0,是否需要上下翻转V坐标。
					//由于例子用的是视频插件生成的RenderTexture,没有Repeat,所以不能直接UV坐标乘以-1,改为用1-V坐标
					if(_ProjectionParams.x < 0)
					{
						screenUV.y = 1 - screenUV.y;
					}
					//用屏幕UV采样贴图,得到颜色1
					half4 col = tex2D(_MainTex, screenUV);

					//用正常模型坐标采样贴图,得到颜色2
					half4 col2 = tex2D(_MainTex, i.uv);
					//用模型坐标采样一张噪声贴图,用于混合颜色1和颜色2
					float noiseUV = i.uv*_noiseMap_ST.xy + _noiseMap_ST.zw;
					noiseUV.x += _Time.y*_speed;
					float4 noiseCol = tex2D(_noiseMap, noiseUV);
					float noiseVal = step(0.5, noiseCol.r);
					float4 finalCol = col * noiseVal + col2 * (1 - noiseVal);

					return finalCol;
				}
				ENDCG
			}
		}
}

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

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

相关文章

26.Spring-AOP(切面编程)

目录 一、Spring-AOP。 &#xff08;1&#xff09;AOP的简介。 &#xff08;2&#xff09;AOP的底层实现-动态代理。 &#xff08;2.1&#xff09;JDK的动态代理。 &#xff08;2.2&#xff09;cglib的动态代理。 &#xff08;3&#xff09;AOP的相关概念。 &#xff0…

【Linux】5、使用 Linux 快捷按键小技巧

目录 一、CTRL C二、CTRL D三、history 命令四、CTRL R五、光标移动快捷方式六、清屏 一、CTRL C &#x1f941; ① 可用于强制停止某些程序的运行 &#x1f941; ② 若命令输入错误&#xff0c;可用它退出当前命令 二、CTRL D &#x1f941; ① 退出登录的账户 &#…

WEB APIs day2

一、Dom事件基础 1.事件监听&#xff08;绑定&#xff09; 1.1 事件监听 一旦绑定后&#xff0c;这个函数不会立即执行的&#xff0c;事件什么时候触发什么时候执行 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8">…

Pyinstaller打包python文件太大?教你三个小技巧有效减小文件体积

简介 有时候需要在未安装Python环境的平台上运行py程序&#xff0c;使用pyinstaller打包很方便&#xff0c;但打包后的可执行文件实在是太大了。原因在于打包时pyinstaller本就已经关联了很多的python内联模块&#xff0c;加上我们项目中存在过多第三方类库&#xff0c;打包的…

优思学院|质量人如何利用ChatGPT提升工作效率?

在许多人知道怎么用ChatGPT之后&#xff0c;不少人开始思考如何利用这个工具来提升自己的工作效率。 质量人也不例外&#xff0c;在质量管理中&#xff0c;有许多重复的任务需要人手去完成。这些任务可能包括检查文档、审查流程、跟踪错误等。这些任务既耗费时间&#xff0c;又…

MAVEN环境变量配置(Windows 11)

1、直接在搜索框中搜&#xff1a;编辑系统环境变量 2、点击环境变量 3、 在系统变量里面新建系统变量 变量名&#xff1a;MAVEN_HOME 变量值&#xff1a;路径一定要写到maven的bin目录下 以下这种写法是错误的 4、新建系统变量完成 5、 往下滑 找到path&#xff0c;可以双击…

【Python】实战:生成无关联单选问卷 csv《跌倒风险评估量表》

目录 一、适用场景 二、业务需求 三、Python 文件 &#xff08;1&#xff09;创建文件 &#xff08;2&#xff09;代码示例 四、csv 文件 一、适用场景 实战场景&#xff1a; 问卷全部为单选题问卷问题全部为必填问题之间无关联关系每个问题的答案分数不同根据问卷全部问…

亚马逊云科技CodeWhisperer正式可用,面向个人开发者免费开放

亚马逊云科技致力于推动生成式AI技术的普惠化&#xff1a;亚马逊云科技将这些技术从研究和实验领域释放出来&#xff0c;不只是少数初创公司和资金雄厚的大型科技公司&#xff0c;而是让更多公司都能从中受益。因此&#xff0c;亚马逊云科技宣布数项创新&#xff0c;帮助客户更…

STM32-HAL-usDelay

一、STM32单片机的延时 STM32单片机的延时&#xff0c;是指在程序中暂停一段时间&#xff0c;等待一定的时间后再继续执行下一条指令。常见的延时方式有循环延时和定时器延时。 毫秒延时的使用场景&#xff1a; 等待外设完成某项操作&#xff1a;在使用外设时&#xff0c;有…

【安全与风险】总结篇

总结篇 期望学习效果学习关键点安全基础一些术语安全策略CIA 密码学概论对称vs非对称对称密码:定义非对称密码学(公钥密码学)密钥生成加密解密技术反向使用:数字签名 基础计算资源安全访问控制列表读、写、执行权限位DoS攻击 恶意软件什么是恶意软件恶意软件的类型基于主机的恶…

SpringBoot中集成任务调度

文章目录 SpringBoot中集成任务调度1. 任务调度基本介绍2. corn表达式介绍2-1 corn的每一个位置功能介绍2-2 占位符说明2-3 常用cron举例 3. SpringBoot项目中&#xff0c;集成任务调度Scheduled3-1 添加SpringBoot启动依赖3-2 具体corn任务调度计划3-3 SpringBoot启动类添加注…

java如何实现深拷贝(IT枫斗者)

java如何实现深拷贝 Java浅拷贝 浅拷贝是按位拷贝对象&#xff0c;它会创建一个新对象&#xff0c;这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型&#xff0c;拷贝的就是基本类型的值&#xff1b;如果属性是内存地址&#xff08;引用类型&#xff09;&#…

2016湖南湘潭邀请赛b题思路

最近训练时写的比赛&#xff0c;当时b题没写&#xff0c;事后补一下&#xff0c;看了下题解&#xff0c;想写下自己的解释 原题解&#xff1a;2016湖南湘潭邀请赛题解&#xff1a;2016年“长城信息”杯中国大学生程序设计比赛中南地区邀请赛&#xff08;迟来的题解&#xff09…

Koordinator 一周年,新版本 v1.2.0 支持节点资源预留,兼容社区重调度策略

作者&#xff1a;佑祎、吕风 背景 Koordinator 是一个开源项目&#xff0c;基于阿里巴巴在容器调度领域多年累积的经验孵化诞生&#xff0c;可以提升容器性能&#xff0c;降低集群资源成本。通过混部、资源画像、调度优化等技术能力&#xff0c;能够提高延迟敏感的工作负载和…

第3章:select

1.最基本的select语句 select … from…select 字段1&#xff0c;字段2&#xff0c;…from 表名* 表中所有字段&#xff08;列&#xff09; 2.列的别名 字段1 as 别名1字段1 别名1as&#xff1a;alias&#xff08;别名&#xff09;可以省略如果别名有空格使用一对””引起来…

应用于音箱领域中的音频功放IC型号推荐

音箱音频功放ic俗称“扩音机”又叫音频功率放大器IC&#xff1b;是各类音响器材中不可缺少的部分&#xff0c;其作用主要是将音源器材输入的较微弱信号进行放大后&#xff0c;产生足够大的电流去推动扬声器进行声音的重放。 现如今&#xff0c;音频功放芯片伴随着人工交互及智…

APS中零件工序间的移动方式解析

在加工装配的成批生产类型企业里&#xff0c;由于零件多种多样&#xff0c;工艺路线、加工方法和技术装备千差万别&#xff0c;因而&#xff0c;产品有多种流转方式。一般来说&#xff0c;零件在各道工序间的移动方式主要有顺序移动、平行移动和平行顺序&#xff08;平顺&#…

网络威胁情报:数据的力量

在一个日益互联和数字化的世界中&#xff0c;网络威胁已成为一项重大挑战&#xff0c;可能危及您组织的声誉、财务稳定性和整体运营效率。 事实上&#xff0c;根据 IBM 2022 年的一份报告&#xff0c;数据泄露的平均成本现在为 435 万美元。 鉴于网络威胁的重要性和影响日益突…

Spring《三》DI 依赖注入

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; 上一篇&#xff1a;Spring《二》bean 的实例化与生命周期 下一篇&#xff1a;敬请期待 目录 一、setter 注入&#x1f349;1.注入引用数据类型2.注入简单数据类型 二、构造器注入&#x1f34a;1.注入引用数据类型2.…

吴恩达团队AI诊断心律失常研究:准确率超人类医生

2019年&#xff0c;吴恩达团队在AI医疗领域实现了一项革命性的突破&#xff0c;他们成功地让AI诊断心律失常&#xff0c;其准确率高达83.7%&#xff0c;超过了人类心脏病医生的78.0%。这项研究成果已经发表在了知名期刊Nature Medicine上。 一、如何让AI学会诊断心律失常&…