unity urp 视差卡牌

总体效果大概四层,从后往前排序为:卡背、背景、画像、边框

首先卡背比较简单,只要判断如果网格的背面就直接采样卡背图片展示即可

资源准备:

然后是背景,网上找到一张这样的图。

但他还不符合要求,我们的背景需要四方接续否则在视差下会看到不连续的接痕。关于如何处理四方接续的图。

首先是把这张图拽进ps里,裁切到512X512,然后在滤镜-其他-位移,将其水平垂直都移动512/2个像素,随后修补接痕位置使其连续即可。

然后是画像,这张图看过我上一个文章的应该很熟悉,而且我认为是很有趣的一件事,推荐去看一眼。Unity图片导入趣事随笔-CSDN博客

最后是边框,直接加在最顶层,这也是图片背景使用黑色的理由。

资源完毕,还需要视差的思路。红色为原本物体的uv位置,绿色是视觉上存在深度后所延长到的uv位置,理论上不需要计算z向量,但为了方便计算,原本物体的uv位置的z分量定为0。在红色上顶点的切线空间中,是右手坐标系,z向量向外,所以深度向量一定为(0,0,-1)根据这两个向量点乘可以求出深度向量和视角向量的cosθ,就可以根据深度反推出视角向量延长的距离,那么原本物体的uv位置 + 视角向量延长的距离就是视觉上存在深度后所延长到的uv位置,随后舍弃z分量就是视觉上存在深度后的uv位置。

这个方法根据输入的原uv坐标、视角向量(切线空间下)和深度来返回视觉上存在深度后的uv坐标

            float2 CalculateRealUVAfterDepth(float2 originUV, float3 viewDirTS, float depth){//计算视角方向和深度方向的cos值float cosTheta = dot(normalize(viewDirTS), float3(0,0,-1));  //  一般来讲unity是左手坐标系,但在切线和观察空间较为特殊是右手坐标系,不过这并不影响z轴方向的判断//根据深度差算出两点间距离float dis = depth / cosTheta;//算出应用深度差后对应点位float3 originUVPoint = float3(originUV, 0);float3 afrerDepthUVPoint = originUVPoint + normalize(viewDirTS) * dis;//返回应用深度差后对应UVreturn afrerDepthUVPoint.xy;}

根据这些视差过后的uv坐标采样图片并叠加,就能做出视觉上有距离感的图片结构。

Shader "Kerzh/Tarol"
{Properties{[Space(50)]_FrameTexture("FrameTexture",2D) = "Black"{}[Space(50)]_ParallaxTexture1("Parallax Texture1",2D) = "Black"{}_ParallaxDepth1("Parallax Depth1",Float) = 0[Space(50)]_ParallaxTexture2("Parallax Texture2",2D) = "Black"{}_ParallaxDepth2("Parallax Depth2",Float) = 0_FlowVector2AndSpeed("FlowVector2AndSpeed",Vector) = (0,0,0,0)[Space(50)]_BackTexture("_BackTexture",2D) = "Black"{}}SubShader{Tags {"RenderPipeline" = "UniversalRenderPipeline" "Queue" = "Geometry" "RenderType" = "ReplaceMePlease" "ForceNoShadowCasting" = "false" "DisableBatching" = "False" "IgnoreProjector" = "False" "PreviewType" = "Plane"}LOD 100Pass{Cull OffCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#include  "CommonCgInclude.cginc"V2FData vert (MeshData input){V2FData output = FillBaseV2FData(input);return output;}sampler2D _FrameTexture;float4 _FrameTexture_ST;sampler2D _ParallaxTexture1;float4 _ParallaxTexture1_ST;float _ParallaxDepth1;sampler2D _ParallaxTexture2;float4 _ParallaxTexture2_ST;float _ParallaxDepth2;vector _FlowVector2AndSpeed;sampler2D _BackTexture;float4 _BackTexture_ST;float2 CalculateRealUVAfterDepth(float2 originUV, float3 viewDirTS, float depth){//计算视角方向和深度方向的cos值float cosTheta = dot(normalize(viewDirTS), float3(0,0,-1));  //  一般来讲unity是左手坐标系,但在切线和观察空间较为特殊是右手坐标系,不过这并不影响z轴方向的判断//根据深度差算出两点间距离float dis = depth / cosTheta;//算出应用深度差后对应点位float3 originUVPoint = float3(originUV, 0);float3 afrerDepthUVPoint = originUVPoint + normalize(viewDirTS) * dis;//返回应用深度差后对应UVreturn afrerDepthUVPoint.xy;}fixed4 frag (V2FData input,float backFace:VFace) : SV_Target{float3 tangentWS = normalize(input.tangentWS);float3 normalWS = normalize(input.normalWS);float3 bitangentWS = normalize(input.bitangentWS);float3 lightDirWS = normalize(UnityWorldSpaceLightDir(input.posWS.xyz));float3 viewDirWS = normalize(UnityWorldSpaceViewDir(input.posWS.xyz));float2 uv = input.uv;//背面处理if(backFace<0){float2 backUV = float2(1-uv.x,uv.y);float4 backTextureSample = tex2D(_BackTexture,backUV*_BackTexture_ST.xy + _BackTexture_ST.zw);return backTextureSample;}//下面都是正面的了float3x3 TBN_WS2TS = float3x3(tangentWS,bitangentWS,normalWS);  //  世界-》切线变换矩阵float3 viewDirTS = mul(TBN_WS2TS, viewDirWS);//为什么需要在切线空间计算呢?因为深度值是相对于切线空间定义的//计算经深度值影响过后的uvfloat2 uv1AfterDepth = CalculateRealUVAfterDepth(uv, viewDirTS, _ParallaxDepth1);float2 uv2AfterDepth = CalculateRealUVAfterDepth(uv, viewDirTS, _ParallaxDepth2);//采样视差图1uv1AfterDepth = saturate(uv1AfterDepth);float4 _ParallaxTexture1Sample = tex2D(_ParallaxTexture1,uv1AfterDepth*_ParallaxTexture1_ST.xy + _ParallaxTexture1_ST.zw);//采样视差图2uv2AfterDepth += -_FlowVector2AndSpeed.xy * _Time.y * _FlowVector2AndSpeed.z;float4 _ParallaxTexture2Sample = tex2D(_ParallaxTexture2,uv2AfterDepth*_ParallaxTexture2_ST.xy + _ParallaxTexture2_ST.zw);//采样边框float4 _FrameTextureSample = tex2D(_FrameTexture,uv*_FrameTexture_ST.xy + _FrameTexture_ST.zw);float4 finalCol = float4(0,0,0,1);finalCol = _ParallaxTexture2Sample;finalCol = lerp(finalCol,_ParallaxTexture1Sample,_ParallaxTexture1Sample.a);finalCol += _FrameTextureSample;return finalCol;}ENDCG}}
}

库文件:CommonCGinclude.cginc

#ifndef COMMONCGINCLUDE
#define COMMONCGINCLUDEstruct MeshData
{float4 vertex : POSITION;float2 uv : TEXCOORD0;float2 uv2 : TEXCOORD1;float4 tangentOS :TANGENT;float3 normalOS : NORMAL;float4 vertexColor : COLOR;
};struct V2FData
{float4 pos : SV_POSITION; // 必须命名为pos ,因为 TRANSFER_VERTEX_TO_FRAGMENT 是这么命名的,为了正确地获取到Shadowfloat2 uv : TEXCOORD0;float3 tangentWS : TEXCOORD1;float3 bitangentWS : TEXCOORD2;float3 normalWS : TEXCOORD3;float3 posWS : TEXCOORD4;float3 posOS : TEXCOORD5;float3 normalOS : TEXCOORD6;float4 vertexColor : TEXCOORD7;float2 uv2 : TEXCOORD8;
};V2FData FillBaseV2FData(MeshData input)
{V2FData output;output.pos = UnityObjectToClipPos(input.vertex);output.uv = input.uv;output.uv2 = input.uv2;output.normalWS = normalize(UnityObjectToWorldNormal(input.normalOS));output.posWS = mul(unity_ObjectToWorld, input.vertex);output.posOS = input.vertex.xyz;output.tangentWS = normalize(UnityObjectToWorldDir(input.tangentOS));output.bitangentWS = cross(output.normalWS, output.tangentWS) * input.tangentOS.w; //乘上input.tangentOS.w 是unity引擎的bug,有的模型是 1 有的模型是 -1,必须这么写output.normalOS = input.normalOS;output.vertexColor = input.vertexColor;return output;
}#endif

在面板上这样赋值即可获得这样的效果

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

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

相关文章

Tomcat源码解析(一): Tomcat整体架构

Tomcat源码系列文章 Tomcat源码解析(一)&#xff1a; Tomcat整体架构 目录 一、Tomcat整体架构1、Tomcat两个核心组件功能2、Tomcat支持的多种I/O模型和应用层协议 二、Connector连接器1、连接器功能汇总2、ProtocolHandler组件2.1、Endpoint2.2、Processor 3、Adapter组件 三…

好大夫问诊数据爬虫记录

好大夫问诊数据爬虫入库字段记录 获取医生的病程列表 uid Column(Integer, primary_keyTrue, autoincrementTrue) gender Column(String(10)) # 性别 age Column(Integer) # 年龄 # 总交流次数 total_communication_times Column(Integer) # 医生回复次数 doctor_reply_t…

uniapp 编译后文字乱码的解决方案

问题: 新建的页面中编写代码&#xff0c;其中数字和图片都可以正常显示&#xff0c;只有中文编译后展示乱码 页面展示也是乱码 解决方案: 打开HuilderX编辑器的【文件】- 【以指定编码重新打开】- 【选择UTF-8】 然后重新编译就可以啦~ 希望可以帮到你啊~

2023极客大挑战web小记

拿到题目提示post传参还以为是道签到题 刚开始直接把自己极客大挑战的username以及password怼上去&#xff0c;但是不对。看看F12&#xff0c;有提示。 当一个搜索蜘蛛访问一个站点时&#xff0c;它会首先检查该站点根目录下是否存在robots.txt&#xff0c;如果存在&#xff0c…

部署Tomcat及其负载均衡

Tomcat服务器是一个免费的开放源代码的Web应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试JSP程序的首选。一般来说&#xff0c;Tomcat虽然和Apache或者Nginx这些Web服务器一样&#xf…

CSS 下载进度条

<template><view class=btn>下载中</view></template><script></script><style>/* 设置整个页面的样式 */body {width: 100vw; /* 页面宽度为视口宽度 */background: #000000; /* 背景颜色为白色 */display: flex; /* 使用 flex…

linux GDB and GDB Sever

概念&#xff1a; GDB&#xff08;GNU Debugger&#xff09;是一个用于调试程序的强大工具。它是GNU项目的一部分&#xff0c;支持多种编程语言&#xff0c;包括C、C等。GDB 提供了一组命令和功能&#xff0c;允许跟踪检查程序的内部状态&#xff0c;跟踪代码的执行过程&#…

MySQL题目示例

文章目录 1.题目示例 1.题目示例 09&#xff09;查询学过「张三」老师授课的同学的信息 SELECT s.*, c.cname, t.tname, sc.score FROM t_mysql_teacher t, t_mysql_course c, t_mysql_student s, t_mysql_score sc WHERE t.tid c.tid AND c.cid sc.cid AND sc.sid s.sid …

一种具有轨迹优化的无人驾驶车实时运动规划器 论文阅读

论文题目&#xff1a;A Real-Time Motion Planner with Trajectory Optimization for Autonomous Vehicles Abstract 本文的实时规划器首先将空间离散化&#xff0c;然后基于一组成本函数搜索出最佳轨迹。迭代优化所得到的轨迹的Path和Speed。post-optimization计算复杂度低&…

TF-IDF(Term Frequency-Inverse Document Frequency)算法详解

目录 概述 术语解释 词频&#xff08;Term Frequency&#xff09; 文档频率&#xff08;Document Frequency&#xff09; 倒排文档频率&#xff08;Inverse Document Frequency&#xff09; 计算&#xff08;Computation&#xff09; 代码语法 代码展示 安装相关包 测…

邮件开发客户:从吸引潜在客户到提高转化率的实用指南

做外贸的很多企业都习惯使用邮件作为沟通工具&#xff0c;所以我们也可以利用邮件发送开发信来进行客户开发。 为什么外贸企业喜欢使用邮件呢&#xff1f; 1、使用习惯 不同于我们国家习惯使用微信沟通&#xff0c;邮件始终是外国人在进行商务、营销、日常沟通等场合下常用且重…

基于OCR的包装产品生产日期识别系统

基于OCR的包装产品生产日期识别系统 背景技术方案PaddleOCR模型应用数据挑战与解决方案优化策略 项目实施步骤结果与展望 背景 在工业生产中&#xff0c;产品包装上的生产日期信息是至关重要的&#xff0c;它关系到物资的时效性和质量。为了更快、更准确地提取这些信息&#x…

Redis中的Java客户端

一、Jedis Jedis是一个Java实现的Redis客户端连接工具。 Jedis使用非常简单&#xff0c;直接引入依赖。基于默认参数的Jedis连接池&#xff0c;初始化连接池类&#xff08;使用默认连接池参数&#xff09;JedisPool&#xff0c;获取一个Jedis连接Jedis jedisjp.getResource()…

.NET core 中的Kestrel 服务器

什么是Kestrel&#xff1f; Kestrel 是一个跨平台的Web服务器&#xff0c;会默认在ASP.NET Core 项目模板中对其进行配置。未使用 IIS 托管时&#xff0c;ASP.NET Core 项目模板默认使用 Kestrel。 Kestrel 的功能包括&#xff1a; 跨平台&#xff1a;Kestrel 是可在 Window…

从零开始的源码搭建:详解连锁餐饮行业中的点餐小程序开发

时下&#xff0c;点餐小程序成为了许多餐饮企业引入的一种创新工具&#xff0c;不仅方便了顾客的用餐体验&#xff0c;同时也提高了餐厅的运营效率。本文将详细探讨如何从零开始搭建一个源码&#xff0c;并深入解析连锁餐饮行业中的点餐小程序开发过程。 一、需求分析与规划 在…

如何使用Flash模拟EEPROM

目录 1、FLASH与EEPROM简介 2、FLASH模拟EEPROM原理 2.1、EERPOM数据结构 2.2、EERPOM物理结构 在讲解这篇博文前&#xff0c;首先要明白为什么使用Flash存储来模拟EEPROM&#xff1f; 主要有以下几个原因&#xff1a; 成本效益&#xff1a;许多微控制器(MCU)和系统芯片(SoC)内…

统计学-R语言-4.2

文章目录 前言单变量数据的描述分析分类型数据频数表条形图饼图 数值型数据数值型数据数据的集中趋势--均值数据的集中趋势--众数 离散程度离散程度--极差离散程度--四分位数极差离散程度--方差离散程度--加权方差离散程度--标准差离散程度--变异系数 数据的形状数据的形状--偏…

高级分布式系统-第7讲 分布式系统的时钟同步

顺序的分类 在分布式系统中&#xff0c; 顺序关系主要分为以下三类&#xff1a;时间顺序&#xff1a; 事件在时间轴上发生的先后关系。 无限时刻集组成有向时间轴&#xff0c; 时间顺序是通过时刻的顺序体现的。 因果顺序&#xff1a; 如果事件e1是事件e2发生的原因&#xf…

数据分析概述2(详细介绍机器学习

目录 1.名词解释&#xff1a;1.1算法和模型1.2参数和超参数 2.基础算法&#xff1a;3.高级算法&#xff1a;4.数据准备5.常用python包小结&#xff1a; 1.名词解释&#xff1a; 1.1算法和模型 算法&#xff1a;用于训练模型的方法&#xff0c;分为有监督学习、无监督学习、半…

Logstash:迁移数据到 Elasticsearch

在生产环境中&#xff0c;不使用 Apache Kafka 等流平台进行数据迁移并不是一个好的做法。 在这篇文章中&#xff0c;我们将详细探讨 Apache Kafka 和 Logstash 的关系。 但首先让我们简单了解一下 Apache Kafka 的含义。 Apache Kafka 是分布式流平台&#xff0c;擅长实时数据…