Unity中Shader面片一直面向摄像机

2024-01-08 12:28

本文主要是介绍Unity中Shader面片一直面向摄像机,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、实现思路
    • 1、 我们要实现模型面片一直跟着摄像机旋转,那么就需要用到旋转矩阵
    • 2、确定 原坐标系 和 目标坐标系
    • 3、确定旋转后坐标系基向量
  • 二、确定旋转后 坐标系基向量 在 原坐标系 下的值
    • 1、Z轴基向量
    • 2、假设Y轴基向量 和 世界空间下 的Y轴方向一致竖直向上
    • 3、X轴基向量
    • 4、Y轴基向量
  • 三、顶点应用旋转
    • 法一:向量乘法
    • 法二:矩阵乘法
    • 最后转化到齐次裁剪空间
  • 四、最终效果
    • 最终测试代码


前言

在之前的文章中,我们实现了Shader的序列帧动画。

  • Unity中Shader序列帧动画(总结篇)

但是,我们会发现,我们的面片不会一直面向摄像机,当摄像机移动时,人物或特效就会出现穿帮的效果。所以,我们接下来就来实现让我们的面片面向摄像机。

类似的功能,还可能用于:特效、公告牌、八方旅人风格效果、饥荒风格效果。


一、实现思路

1、 我们要实现模型面片一直跟着摄像机旋转,那么就需要用到旋转矩阵

  • Unity中Shader旋转矩阵(二维旋转矩阵)
  • Unity中Shader旋转矩阵(四维旋转矩阵)
  • Unity中Shader矩阵变换的几何体现

2、确定 原坐标系 和 目标坐标系

  • 原坐标系 就是模型的本地坐标
    在这里插入图片描述
  • 目标坐标系
    因为我们的面片需要一直朝向摄像机。
    所以,可以确定旋转后的坐标系Z轴方向 需要 和 原模型本地空间坐标系原点 指向 摄像机 方向一致。
    在这里插入图片描述

3、确定旋转后坐标系基向量


二、确定旋转后 坐标系基向量 在 原坐标系 下的值

1、Z轴基向量

  • 求 摄像机坐标 在模型本地空间下的坐标值,在 归一化后 就是 Z轴基向量

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

2、假设Y轴基向量 和 世界空间下 的Y轴方向一致竖直向上

在这里插入图片描述

float3 upDir = float3(0,1,0);

3、X轴基向量

  • X轴基向量 = Z轴基向量 × Y轴基向量

  • 叉积 的顺序取决于 坐标系类型 (逆时针叉积)

  • 模型本地空间坐标系为左手坐标系
    在这里插入图片描述

  • 左手坐标系中,X轴 = 食指 × 拇指 = Z × Y

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

4、Y轴基向量

  • Y轴基向量 = X轴基向量 × Z轴基向量
  • 叉积 的顺序取决于 坐标系类型 (逆时针叉积)
  • 模型本地空间坐标系为左手坐标系
  • 左手坐标系中,Y轴 = 中指 × 食指 = X × Z

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


三、顶点应用旋转

法一:向量乘法

  • n e w P o s O S = X 基向量 ∗ p o s O S x + Y 基向量 ∗ p o s O S y + Z 基向量 ∗ p o s O S z newPosOS = X基向量*posOS_x + Y基向量*posOS_y+Z基向量*posOS_z newPosOS=X基向量posOSx+Y基向量posOSy+Z基向量posOSz

float3 newVertexOS = rightDir * v.vertexOS.x + upDir * v.vertexOS.y + viewDir * v.vertexOS.z;

法二:矩阵乘法

float4x4 M = float4x4
(
rightDir.x,upDir.x,viewDir.x,0,
rightDir.y,upDir.y,viewDir.y,0,
rightDir.z,upDir.z,viewDir.z,0,
0,0,0,1
);
float3 newVertexOS = mul(M,v.vertexOS).xyz;

最后转化到齐次裁剪空间

o.vertexCS = TransformObjectToHClip(newVertexOS);


四、最终效果

请添加图片描述

最终测试代码

Shader "MyShader/URP/P3_10_1"
{Properties{[Enum(UnityEngine.Rendering.BlendMode)]_SrcFactor("SrcFactor",int) = 0[Enum(UnityEngine.Rendering.BlendMode)]_DstFactor("DstFactor",int) = 0_Color("Color",Color) = (1,1,1,1)_MainTex("MainTex",2D) = "white"{}_Sequence("Row(X) Column(Y) Speed(Z)",Vector) = (1,1,1,1)}SubShader{Tags{//告诉引擎,该Shader只用于 URP 渲染管线"RenderPipeline"="UniversalPipeline"//渲染类型"RenderType"="Transparent"//渲染队列"Queue"="Transparent"}Blend [_SrcFactor] [_DstFactor]Pass{HLSLPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fog#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"struct Attribute{float4 vertexOS : POSITION;float2 uv : TEXCOORD0;};struct Varying{float4 vertexCS : SV_POSITION;float2 uv : TEXCOORD1;float fogCoord : TEXCOORD2;};CBUFFER_START(UnityPerMaterial)float4 _Color;float4 _MainTex_ST;half4 _Sequence;CBUFFER_ENDTEXTURE2D(_MainTex);SAMPLER(sampler_MainTex);Varying vert(Attribute v){Varying o;//Z轴基向量float3 viewDir = mul(GetWorldToObjectMatrix(),float4(_WorldSpaceCameraPos,1)).xyz;viewDir = normalize(viewDir);//假设Y轴基向量float3 upDir = float3(0,1,0);//X轴基向量(左手坐标系、逆时针叉乘)float3 rightDir = normalize(cross(viewDir,upDir));//Y轴基向量(左手坐标系、逆时针叉乘)upDir = normalize(cross(rightDir,viewDir));//顶点应用旋转//法一:向量乘法float3 newVertexOS = rightDir * v.vertexOS.x + upDir * v.vertexOS.y + viewDir * v.vertexOS.z;//法二:矩阵乘法/*float4x4 M = float4x4(rightDir.x,upDir.x,viewDir.x,0,rightDir.y,upDir.y,viewDir.y,0,rightDir.z,upDir.z,viewDir.z,0,0,0,0,1);float3 newVertexOS = mul(M,v.vertexOS).xyz;*/o.vertexCS = TransformObjectToHClip(newVertexOS);o.uv = float2(v.uv.x / _Sequence.y, v.uv.y / _Sequence.x + (_Sequence.x - 1) / _Sequence.x);o.uv.x += frac(floor(_Time.y * _Sequence.y * _Sequence.z) / _Sequence.y);o.uv.y -= frac(floor(_Time.y * _Sequence.y * _Sequence.z / _Sequence.y) / _Sequence.x);//o.uv.x += floor(_Time.y);//o.uv = float2(v.uv.x/4,v.uv.y/4);//o.uv = TRANSFORM_TEX(v.uv,_MainTex);o.fogCoord = ComputeFogFactor(o.vertexCS.z);return o;}half4 frag(Varying i) : SV_Target{float4 mainTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);float4 col = mainTex * _Color;col.rgb = MixFog(col.rgb, i.fogCoord);col.rgb = col.rgb * col.a;return col;}ENDHLSL}}}

这篇关于Unity中Shader面片一直面向摄像机的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》P98

更改为 差分的数学表达式从泰勒级数展开式可得: 后悔没听廖老师的。 禹晶、肖创柏、廖庆敏《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》 禹晶、肖创柏、廖庆敏《数字图像处理》资源二维码

Unity Post Process Unity后处理学习日志

Unity Post Process Unity后处理学习日志 在现代游戏开发中,后处理(Post Processing)技术已经成为提升游戏画面质量的关键工具。Unity的后处理栈(Post Processing Stack)是一个强大的插件,它允许开发者为游戏场景添加各种视觉效果,如景深、色彩校正、辉光、模糊等。这些效果不仅能够增强游戏的视觉吸引力,还能帮助传达特定的情感和氛围。 文档

实例demo理解面向接口思想

浅显的理解面向接口编程 Android开发的语言是java,至少目前是,所以理解面向接口的思想是有必要的。下面通过一个简单的例子来理解。具体的概括我也不知道怎么说。 例子: 现在我们要开发一个应用,模拟移动存储设备的读写,即计算机与U盘、MP3、移动硬盘等设备进行数据交换。已知要实现U盘、MP3播放器、移动硬盘三种移动存储设备,要求计算机能同这三种设备进行数据交换,并且以后可能会有新的第三方的

Unity协程搭配队列开发Tips弹窗模块

概述 在Unity游戏开发过程中,提示系统是提升用户体验的重要组成部分。一个设计良好的提示窗口不仅能及时传达信息给玩家,还应当做到不干扰游戏流程。本文将探讨如何使用Unity的协程(Coroutine)配合队列(Queue)数据结构来构建一个高效且可扩展的Tips弹窗模块。 技术模块介绍 1. Unity协程(Coroutines) 协程是Unity中的一种特殊函数类型,允许异步操作的实现

Unity 资源 之 Super Confetti FX:点亮项目的璀璨粒子之光

Unity 资源 之 Super Confetti FX:点亮项目的璀璨粒子之光 一,前言二,资源包内容三,免费获取资源包 一,前言 在创意的世界里,每一个细节都能决定一个项目的独特魅力。今天,要向大家介绍一款令人惊艳的粒子效果包 ——Super Confetti FX。 二,资源包内容 💥充满活力与动态,是 Super Confetti FX 最显著的标签。它宛如一位

Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(4)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(3)-CSDN博客  这节就是真正的存储数据了   理清一下思路: 1.存储路径并检查 //2进制文件类存储private static string Data_Binary_Pa

Unity Adressables 使用说明(一)概述

使用 Adressables 组织管理 Asset Addressables 包基于 Unity 的 AssetBundles 系统,并提供了一个用户界面来管理您的 AssetBundles。当您使一个资源可寻址(Addressable)时,您可以使用该资源的地址从任何地方加载它。无论资源是在本地应用程序中可用还是存储在远程内容分发网络上,Addressable 系统都会定位并返回该资源。 您

行为智能识别摄像机

行为智能识别摄像机 是一种结合了人工智能技术和监控摄像技术的先进设备,它能够通过深度学习算法对监控画面进行实时分析,自动识别和分析监控画面中的各种行为动作。这种摄像机在安防领域有着广泛的应用,可以帮助监控人员及时发现异常行为,并采取相应的措施。 行为智能识别摄像机可以有效预防盗窃事件。在商场、超市等公共场所安装这种摄像机,可以通过识别异常行为等情况,及时报警并阻止不安全行为的发生

Unity Adressables 使用说明(六)加载(Load) Addressable Assets

【概述】Load Addressable Assets Addressables类提供了加载 Addressable assets 的方法。你可以一次加载一个资源或批量加载资源。为了识别要加载的资源,你需要向加载方法传递一个键或键列表。键可以是以下对象之一: Address:包含你分配给资源的地址的字符串。Label:包含分配给一个或多个资源的标签的字符串。AssetReference Obj

在Unity环境中使用UTF-8编码

为什么要讨论这个问题         为了避免乱码和更好的跨平台         我刚开始开发时是使用VS开发,Unity自身默认使用UTF-8 without BOM格式,但是在Unity中创建一个脚本,使用VS打开,VS自身默认使用GB2312(它应该是对应了你电脑的window版本默认选取了国标编码,或者是因为一些其他的原因)读取脚本,默认是看不到在VS中的编码格式,下面我介绍一种简单快