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

2024-01-07 17:58:54


前言

在上一篇文章中,我们用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
        }
    }
}

文章来源:https://blog.csdn.net/qq_51603875/article/details/135441360
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。