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_END

            TEXTURE2D(_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
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1.7 day5 IO进程线程

互斥锁 #include <myhead.h> char buf[128];//创建临界资源 pthread_mutex_t mutex;//创建锁 void *task(void *arg)//分支线程 {while(1){pthread_mutex_lock(&mutex);//上锁printf("分支线程:buf%s\n",buf);strcpy(buf,"I Love China");pthre…

mysql基础-表数据操作之查

目录 1.别名 2. 单表查询 2.1 模糊查询 - like 2.2 limit 2.3 order by 2.4 group by 2.5 in 2.6 between and 2.6 is null 2.7 not 2.8 运算符 3. 联表查询 全连接 左连接 右连接 本次分享一下数据的DQL语言。 1.别名 首先分享一下别名的知识。我们在查询的时…

【创建VirtualBox虚拟机并安装openEuler20.03 TLS SP1操作系统】

创建VirtualBox虚拟机并安装openEuler20.03 TLS SP1操作系统 一、环境说明二、安装过程 一、环境说明 虚拟机软件&#xff1a;Virtualbox操作系统&#xff1a;openEuler 20.03 TLS SP1&#xff08;x86&#xff09; 二、安装过程 创新虚拟机 修改虚拟机配置&#xff1a; …

MySQL复习汇总(图书管理系统)

MySQL图书管理系统&#xff08;49-94&#xff09;源码_71.备份book数据库到e盘的mybook.sql文件(备份文件中要求包含建库命令)-CSDN博客 -- 1、 创建一个名称为book的数据库。 -- 2、 打开book数据库 -- 3、 创建数据表分别如下&#xff08;除外键之外&#xff09;…

IDEA 中搭建 Spring Boot Maven 多模块项目 (父SpringBoot+子Maven)

第1步&#xff1a;新建一个SpringBoot 项目 作为 父工程 [Ref] 新建一个SpringBoot项目 删除无用的 .mvn 目录、 src 目录、 mvnw 及 mvnw.cmd 文件&#xff0c;最终只留 .gitignore 和 pom.xml 第2步&#xff1a;创建 子maven模块 第3步&#xff1a;整理 父 pom 文件 ① …

支付宝扫码(Easy版)支付实现

文章目录 一 技术准备1.1 二维码技术&#xff08;java&#xff09;1.2 支付宝沙箱环境准备1.3 内网穿透 二 支付宝支付相关知识2.1 各种支付方式2.2 扫码付接入流程2.3 系统交互流程(时序图)2.4 加密逻辑 三 扫码支付实现3.1 添加maven依赖&#xff08;Easy版&#xff09;3.2 完…

【Python发送邮件】

Python发送邮件 使用python的email和smtplib发送邮件 使用python的email和smtplib发送邮件 需要先下载安装 email 和 smtplib 模块 // An highlighted block pip install email smtplib需要去你的邮件地址申请一下 API Key&#xff0c;这是专门用来开发时使用的密钥。 获取后…

看CHAT如何判断php Imagick writeImages写入gif已经完毕

CHAT回复&#xff1a;Imagick::writeImages() 是同步执行的&#xff0c;也就是说这个函数会阻塞直到 GIF 文件被完全写出。所以如果这个函数没有报错并成功返回&#xff0c;那么你可以认为 GIF 文件已经被完全写出了。 如果你想要在写出 GIF 文件后立即做一些操作&#xff08;例…

学习c语言,隐形类型转换,整形提升

把整形定义字符型的话&#xff0c;字符型指挥提取整形前8位&#xff0c;但是整形有32位&#xff0c;如果字符型最后一位为0全部补0&#xff0c;为1全部补1。

测试分类篇

小王学习录 测试分类按测试对象划分1. 界面测试2. 可靠性测试3. 容错性测试4. 文档测试5. 兼容性测试6. 易用性测试7. 安装卸载测试8. 安全测试9. 性能测试10. 内存泄露测试 按是否查看代码划分1. 黑盒测试2. 白盒测试3. 灰盒测试 按开发阶段分1. 单元测试2. 集成测试3. 系统测…

WebofScience快速检索文献的办法

Web of Science为什么老是搜不到文章&#xff0c;原来是要在这个地方全部勾选 如果是搜标题的话&#xff0c;选Title&#xff0c;输入你要搜的文章标题 另外&#xff0c;也可以在浏览器直接搜文章标题&#xff0c;得到文章的DOI&#xff0c;然后选DOI&#xff0c;直接搜DOI也行…

draw.io基础操作和代码高效画图进阶

文章目录 一、基础操作1、链接2、等比例变形3、复制4、插入表格 二、在线打开三、插入—功能聚集地1、插入图片2、插入画笔3、插入布局4、导出 四、图码转换——高效画图1、通用图码转换2、流程图生成&#xff1a;使用mermaid语言生成图&#xff1a; 五、图码转换高效画图的典型…

超维空间M1无人机使用说明书——52、ROS无人机二维码识别与降落

引言&#xff1a;使用二维码引导无人机实现精准降落&#xff0c;首先需要实现对二维码的识别和定位&#xff0c;可以参考博客的二维码识别和定位内容。本小节主要是通过获取拿到的二维码位置&#xff0c;控制无人机全向的移动和降落&#xff0c;分为两种&#xff0c;一种是无人…

问题:为什么IP和端口一样的两个应用服务可以正常启动呢?

mysql安装 将MongoDB安装好并设置bindIP为0.0.0.0&#xff0c;端口为3306 发现问题&#xff0c;MySQL和MongoDB端口和IP一致&#xff0c;两个服务都能同时启动&#xff0c;这是为什么呢&#xff1f; 麻烦知道的大佬帮忙解答一下~~~

win10下安装detectron2-0.5(0.6应该也可以)

最近从github上下载的实例分割代码是detectron2-0.5的记录下配置过程。 1、前面什么pytorch基本步骤网上教程很多, 对着项目的要求下就行 2、到这里一般都是让你去下一个detectron2&#xff0c;但是我们从github上白嫖的项目都是有detectron2的&#xff0c;所以只需要找到那个s…

DQL命令查询数据(三)

本课目标 掌握MySQL的多表查询 SQL语句的综合应用 多表连接查询 通过各个表之间共同列的关联性&#xff08;例如&#xff1a;外键&#xff09;来查询的 分类&#xff1a; 内连接(INNER JOIN) &#xff0c;可简写为 JOIN&#xff1b;左外连接(LEFT OUTER JOIN)&#xff0c;…

【EAI 004】LLM+P:借助LLM和PDDL赋予机器人最优规划能力

论文标题&#xff1a;LLMP: Empowering Large Language Models with Optimal Planning Proficiency 论文作者&#xff1a;Bo Liu, Yuqian Jiang, Xiaohan Zhang, Qiang Liu, Shiqi Zhang, Joydeep Biswas, Peter Stone 作者单位&#xff1a;Department of Computer Science, Th…

【前端设计】小球loading动画

欢迎来到前端设计专栏&#xff0c;本专栏收藏了一些好看且实用的前端作品&#xff0c;使用简单的html、css语法打造创意有趣的作品&#xff0c;为网站加入更多高级创意的元素。 html <!DOCTYPE html> <html lang"en"> <head><meta charset&quo…

【深度学习:Few-shot learning】理解深入小样本学习中的孪生网络

【深度学习&#xff1a;Few-shot learning】理解深入小样本学习中的孪生网络 深入理解孪生网络&#xff1a;架构、应用与未来展望小样本学习的诞生元学习小样本学习孪生网络的基本概念孪生网络的细节Triplet Loss架构特点关键组件训练过程主要应用领域未来展望示例图片结论 深入…

[AutoSar]基础部分 RTE 06 对runnable的触发和SWC的影响

目录 关键词平台说明一、runnable二、RTE的event2.1Mode类型event2.2周期触发类型2.3 数据交互触发 三、internal runnable value四、专属运行区指定五、per_instance memory 关键词 嵌入式、C语言、autosar、Rte 平台说明 项目ValueOSautosar OSautosar厂商vector芯片厂商T…