当前位置: 首页 > news >正文

URP - 公告牌的效果实现

效果:

【太妃糖耶】我的最新作品,快来一睹为快!

原理:使面片的正面永远跟随摄像机的旋转

首先我们可以了解一下顶点旋转的原理

B点是由原坐标系中的基向量和A点坐标值相乘得到的

当旋转此基向量后,B点的坐标值会发生改变 

所以旋转后顶点的坐标值是由旋转后的基向量在原坐标系下的值乘以原顶点坐标 


根据上面顶点旋转的原理我们来看一下如何让面片的顶点跟随摄像机进行旋转,求得旋转后的面片顶点的坐标值

原模型的顶点坐标是在模型本地坐标系的坐标值

此时就需要知道旋转后坐标系的基向量在原本地坐标系下的值

而模型跟随摄像机旋转后的坐标系的基向量在原本地坐标系下的值如何得到呢?

可以假设Z方向向量为从模型指向摄像机,将摄像机的世界坐标系下的坐标值转换到模型空间再归一化就得到了旋转后的坐标系的基向量在原本地坐标系下的Z方向的基向量

float3 viewDir = mul(GetWorldToObjectMatrix(),float4(_WorldSpaceCameraPos,1));

viewDir = normalize(viewDir);

_WorldSpaceCameraPos为三维数

假设Y方向的基向量为(0,1,0)   :    float3 upDir = float3(0,1,0);

X方向的基向量可以有Y方向和Z方向的基向量叉乘得到

// 模型的本地空间为左手坐标系 默认X轴向右,Y轴向上,Z轴

float3 rightDir = normalize(cross(viewDir,upDir));

通过左手定则,大拇指指向要求的x轴,叉乘时食指代表的数值在前,中指代表的数值在后

upDir = normalize(cross(rightDir,viewDir));

最后根据所求得的基向量乘以原模型的顶点坐标得到:旋转后的模型顶点后相对于原本地坐标系下的坐标值

然后将此坐标值转换到齐次裁剪空间下即可

float3 newVertex = rightDir*v.positionOS.x+upDir*v.positionOS.y+viewDir*v.positionOS.z;

设置面片在垂直方向的显示与否在代码中体现

Shader"unity/UVSeequence"
{Properties{[NoScaleOffset]_MainTex("MainTex",2D)="white"{}_Row("Row",float)=1_Column("Column",float)=1_Speed("Speed",float)=3//枚举,用于设置viewDir向量的y轴分量值是否为0[Enum(Billaboard,1,VerticalBillaboard,0)]_BillaboardType("BillaboardType",int)=1}SubShader{Tags{"RenderPipeline"="UniversalPipeline""Queue"="Transparent"}//常用于透贴// Blend SrcAlpha OneMinusSrcAlpha//用于黑底图片Blend One OnePass{HLSLPROGRAM#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"#pragma vertex vert#pragma fragment fragTEXTURE2D(_MainTex);float4 _MainTex_ST;#define sampler_MainTex samplerState_Linear_RepeatSAMPLER(sampler_MainTex);CBUFFER_START(UnityPerMaterial)float _Row,_Column,_Speed;int _BillaboardType;CBUFFER_ENDstruct Attributes{float4 positionOS : POSITION;float2 uv : TEXCOORD;};struct Varyings{float4 positionCS : SV_POSITION;float2 uv : TEXCOORD;};Varyings vert(Attributes v){Varyings o = (Varyings)0;//将摄像机的位置转换到模型本地坐标系下float3 viewDir = mul(GetWorldToObjectMatrix(),float4(_WorldSpaceCameraPos,1));//设置垂直方向的显示与否,若不希望面片在垂直方向显示,那么就直接将viewDir向量的y分量设置为0viewDir.y *= _BillaboardType;viewDir = normalize(viewDir);float3 upDir = float3(0,1,0);//模型的本地空间为左手坐标系 默认X轴向右,Y轴向上,Z轴float3 rightDir = normalize(cross(viewDir,upDir));upDir = normalize(cross(rightDir,viewDir));float3 newVertex = rightDir*v.positionOS.x+upDir*v.positionOS.y+viewDir*v.positionOS.z;o.positionCS = TransformObjectToHClip(newVertex);o.uv = TRANSFORM_TEX(v.uv,_MainTex);//序列图动画的起始位置o.uv = float2(v.uv.x/_Column,v.uv.y/_Row+1/_Row*(_Row-1));//frac取小数的作用是优化纹理采样,使得采样纹理的UV在0-1的范围内//U方向上的走格 floor(_Time.y*_Column)/_Column代表一秒钟走完一行中的所以列的格子o.uv.x+=frac(floor(_Time.y*_Column*_Speed)/_Column);//V方向上的走格 floor(_Time.y)/_Row 代表每一秒走一行o.uv.y-=frac(floor(_Time.y*_Speed)/_Row);return o;}float4 frag(Varyings i):SV_Target{float4 c;float4 mainTex = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv);c=mainTex;//用于透贴图片消除Alpah为0的区域 Alpha=1为不透明,Alpha=0为透明c.rgb*=c.a;return c;}ENDHLSL}}}

相关文章:

  • 运维仙途 第2章 日志深渊识异常
  • 《多端统一的终极答案:X5内核增强版的渲染优化全解析》
  • AI赋能烟草工艺革命:虫情监测步入智能化时代
  • 栈与队列 Part 6
  • AI HR新范式:易路iBuilder如何通过“技术隐身,价值凸显”,成为HR身份转型的好帮手
  • 消防岗位技能竞赛流程方案策划
  • 【CUDA pytorch】
  • 基于连接感知的实时困倦分类图神经网络
  • kibana重建es索引
  • ShardingSphere5详细笔记
  • OpenCV-Python (官方)中文教程(部分一)_Day20
  • 软件架构选型之“如何选”
  • 生物化学笔记:神经生物学概论05 感受野 视觉中枢 高级视皮层中的信息走向
  • 【python实用小脚本-43】用Python自动发送生日祝福,让情感更高效
  • 希尔伯特第十问题:是一个伪命题
  • 时态--00--总述
  • 代码随想录打卡|Day31动态规划(最后一块石头的重量2、目标和、一和零)
  • 如何在 Linux 环境下使用 Certbot 自动生成 SSL 证书并部署到 Nginx 服务中
  • POSIX介绍
  • SD - WAN 跨境网络专线部署方式介绍
  • 媒体:酒店、民宿临时毁约涨价,怎么管?
  • 白玉兰奖征片综述丨国产剧集创作的此消彼长
  • 神十九乘组安全顺利出舱
  • 结婚这件事,年轻人到底怎么想的?
  • 海尔智家一季度营收791亿元:净利润增长15%,海外市场收入增超12%
  • 建行一季度净利833.51亿同比下降3.99%,营收降5.4%