Unity中Shader面片一直面向摄像机(个性化修改及适配BRP)

2024-01-07 18:20

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

文章目录

  • 前言
  • 一、个性化修改面向摄像机效果
    • 1、把上一篇文章中求的 Z轴基向量 投影到 XoZ平面上
    • 2、其余步骤和之前的一致
    • 3、在属性面板定义一个变量,控制面片面向摄像机的类型
    • 4、效果
  • 二、适配BRP
  • 三、最终代码


前言

在上一篇文章中,我们用Shader实现了面片一直面向摄像机的效果。

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

在这篇文章中,我们对其进行个性化修改 及 BRP下的适配。


一、个性化修改面向摄像机效果

  • 在很多时候,我们并不需要面片在上下方向跟随摄像机旋转
  • 我们只需要面片跟随摄像机的左右旋转。
  • 那么,我们就需要对上一篇文章中实现的效果进行修改

1、把上一篇文章中求的 Z轴基向量 投影到 XoZ平面上

  • 最简单的办法就是,先把摄像机坐标转化到模型本地坐标
  • 让 y 值为0后,再归一化

float3 viewDir = mul(GetWorldToObjectMatrix(),float4(_WorldSpaceCameraPos,1)).xyz;
viewDir = float3(viewDir.x,0,viewDir.z);
viewDir = normalize(viewDir);

2、其余步骤和之前的一致

  • 假设Y轴基向量
  • 求X轴基向量
  • 求Y轴基向量

3、在属性面板定义一个变量,控制面片面向摄像机的类型

  • 属性面板

[Enum(Billboard,1,VerticalBillboard,0)]_BillboardType(“BillboardType”,int) = 1

  • 在顶点着色器

float3 viewDir = mul(GetWorldToObjectMatrix(),float4(_WorldSpaceCameraPos,1)).xyz;
viewDir.y *= _BillboardType;
viewDir = normalize(viewDir);

4、效果

在这里插入图片描述
请添加图片描述


二、适配BRP

SubShader{Tags{//渲染类型"RenderType"="Transparent"//渲染队列"Queue"="Transparent"}Blend [_SrcFactor] [_DstFactor]Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fog#include "UnityCG.cginc"struct appdata{float3 vertexOS : POSITION;float2 uv : TEXCOORD0;};struct v2f{float4 vertexCS : SV_POSITION;float2 uv : TEXCOORD1;UNITY_FOG_COORDS(2)};float4 _Color;sampler2D _MainTex;float4 _MainTex_ST;half4 _Sequence;half _BillboardType;v2f vert(appdata v){v2f o;//Z轴基向量float3 viewDir = mul(unity_WorldToObject,float4(_WorldSpaceCameraPos,1)).xyz;viewDir.y *= _BillboardType;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 = UnityObjectToClipPos(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);UNITY_TRANSFER_FOG(o, o.vertex)return o;}half4 frag(v2f i) : SV_Target{float4 mainTex = tex2D(_MainTex, i.uv);float4 col = mainTex * _Color;UNITY_APPLY_FOG(i.fogCoord, col)col.rgb = col.rgb * col.a;return col;}ENDCG}}

三、最终代码

Shader "MyShader/URP/P3_10_5"
{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)[Enum(Billboard,1,VerticalBillboard,0)]_BillboardType("BillboardType",int) = 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;half _BillboardType;CBUFFER_ENDTEXTURE2D(_MainTex);SAMPLER(sampler_MainTex);Varying vert(Attribute v){Varying o;//Z轴基向量float3 viewDir = mul(GetWorldToObjectMatrix(),float4(_WorldSpaceCameraPos,1)).xyz;viewDir.y *= _BillboardType;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}}SubShader{Tags{//渲染类型"RenderType"="Transparent"//渲染队列"Queue"="Transparent"}Blend [_SrcFactor] [_DstFactor]Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fog#include "UnityCG.cginc"struct appdata{float3 vertexOS : POSITION;float2 uv : TEXCOORD0;};struct v2f{float4 vertexCS : SV_POSITION;float2 uv : TEXCOORD1;UNITY_FOG_COORDS(2)};float4 _Color;sampler2D _MainTex;float4 _MainTex_ST;half4 _Sequence;half _BillboardType;v2f vert(appdata v){v2f o;//Z轴基向量float3 viewDir = mul(unity_WorldToObject,float4(_WorldSpaceCameraPos,1)).xyz;viewDir.y *= _BillboardType;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 = UnityObjectToClipPos(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);UNITY_TRANSFER_FOG(o, o.vertex)return o;}half4 frag(v2f i) : SV_Target{float4 mainTex = tex2D(_MainTex, i.uv);float4 col = mainTex * _Color;UNITY_APPLY_FOG(i.fogCoord, col)col.rgb = col.rgb * col.a;return col;}ENDCG}}
}

这篇关于Unity中Shader面片一直面向摄像机(个性化修改及适配BRP)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

Linux修改pip和conda缓存路径的几种方法

《Linux修改pip和conda缓存路径的几种方法》在Python生态中,pip和conda是两种常见的软件包管理工具,它们在安装、更新和卸载软件包时都会使用缓存来提高效率,适当地修改它们的缓存路径... 目录一、pip 和 conda 的缓存机制1. pip 的缓存机制默认缓存路径2. conda 的缓

Linux修改pip临时目录方法的详解

《Linux修改pip临时目录方法的详解》在Linux系统中,pip在安装Python包时会使用临时目录(TMPDIR),但默认的临时目录可能会受到存储空间不足或权限问题的影响,所以本文将详细介绍如何... 目录引言一、为什么要修改 pip 的临时目录?1. 解决存储空间不足的问题2. 解决权限问题3. 提

Linux文件名修改方法大全

《Linux文件名修改方法大全》在Linux系统中,文件名修改是一个常见且重要的操作,文件名修改可以更好地管理文件和文件夹,使其更具可读性和有序性,本文将介绍三种在Linux系统下常用的文件名修改方法... 目录一、引言二、使用mv命令修改文件名三、使用rename命令修改文件名四、mv命令和rename命

mybatis-plus 实现查询表名动态修改的示例代码

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示... 目录实现数据库初始化依赖包配置读取类设置 myBATis-plus 插件测试通过 mybatis-plu

Linux下修改hostname的三种实现方式

《Linux下修改hostname的三种实现方式》:本文主要介绍Linux下修改hostname的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下修改ho编程stname三种方式方法1:修改配置文件方法2:hFvEWEostnamectl命

Git如何修改已提交人的用户名和邮箱

《Git如何修改已提交人的用户名和邮箱》文章介绍了如何修改Git已提交人的用户名和邮箱,包括注意事项和具体步骤,确保操作正确无误... 目录git修改已提交人的用户名和邮箱前言第一步第二步总结git修改已提交人的用户名和邮箱前言需注意以下两点内容:需要在顶层目录下(php就是 .git 文件夹所在的目

修改若依框架Token的过期时间问题

《修改若依框架Token的过期时间问题》本文介绍了如何修改若依框架中Token的过期时间,通过修改`application.yml`文件中的配置来实现,默认单位为分钟,希望此经验对大家有所帮助,也欢迎... 目录修改若依框架Token的过期时间修改Token的过期时间关闭Token的过期时js间总结修改若依

MySQL修改密码的四种实现方式

《MySQL修改密码的四种实现方式》文章主要介绍了如何使用命令行工具修改MySQL密码,包括使用`setpassword`命令和`mysqladmin`命令,此外,还详细描述了忘记密码时的处理方法,包... 目录mysql修改密码四种方式一、set password命令二、使用mysqladmin三、修改u

使用Python在Excel中插入、修改、提取和删除超链接

《使用Python在Excel中插入、修改、提取和删除超链接》超链接是Excel中的常用功能,通过点击超链接可以快速跳转到外部网站、本地文件或工作表中的特定单元格,有效提升数据访问的效率和用户体验,这... 目录引言使用工具python在Excel中插入超链接Python修改Excel中的超链接Python