ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【Unity Shader】还原CSGO全息贴纸效果(hologram sticker)

2022-01-20 12:32:15  阅读:456  来源: 互联网

标签:贴纸 normal half4 sticker uv mask Shader param 全息


小伙伴提供的素材:

hologram sticker效果,简称holo:

成果:

基于URP的shader graph实现,以及基于built-in管线的实现


1. 效果分析

在这里可以看到csgo的贴纸效果:StatTrak™ AWP | Man-o'-war (Minimal Wear) | 3D Skin Viewer

根据观察,发现:

a. 全息颜色是根据视角变化的,所以会利用到view direction dot normal direction(视线方向点乘法线方向,即VdotN),即下图的V和N。两个单位向量点乘得到它们夹角的cos值,值越大,夹角越小(想象一下cos曲线)。

       

b. 全息是多层叠加的,每层的颜色以及颜色的变化速度都是不一样的,所以我们会将全息效果写成一个函数,然后调用若干次


2. 实现

基于Unity 2019.4.23

 大致流程是,我们将上图作为色板,将VdotN作为横坐标,纵坐标取固定值。随着视角的变化,shader会在图中横着采样从左到右的彩虹色。我们给贴纸的背景部分使用小的y值,主体使用高的y值,这样背景的颜色发灰,主体颜色很亮。

 ↑这两张图作为mask。根据观察,认为是三层holo叠加,对应mask的rgb通道。

 2.1 全息效果

我们给全息效果制作了一个sub graph:

 讲解下参数:

  • Mask:哪里有全息效果(1),哪里没有效果(0),会把mask图的某个通道传进来
  • Scale:采样色板的快慢,即holo颜色变化快慢
  • Offset:颜色偏移
  • Y Sample Value:色板取色的y值
  • Color Multiplier:取到的颜色的乘数
  • LUT:look up table,色板

 如下图所示,比起通常用uv采样贴图的做法,我们会在uv上叠加VdotN去采样色板,这样视角变化会影响取色。add节点的输入是VdotN和uv。VdotN注意要在object space,如果在world space变化会很鬼畜,可能是数值太大导致的精度问题。uv这里有两个操作。第一个操作是因为色板直接采样,颜色的变化方向是左右,我们需要上下变化,所以把uv split掉后取的是y。第二个操作是scale & offset。我这里控制的是原始uv,读者也可以把它放在别的地方。

 如下图所示,采样LUT后,乘以mask和色彩乘数得到最终结果。 

2.2 多层holo叠加

接下来读取两张mask的三个通道。

这两张图怎么使用读者可以自由决定,我的做法是这样的,并不是所有图都用上了:

 参数:

  • R Scale Offset Y Mult:对应holo节点的四个参数

 

 

单层

叠加

 2.3 转为built-in管线shader

Shader "Unlit/UnlitShader card"
{
    Properties
    {
        _MaskA ("mask a", 2D) = "white" {}
        _MaskB ("mask b", 2D) = "white" {}
        _LUT ("LUT", 2D) = "white" {}
        RParam("R param", Vector) = (1, 0, 0, 1)
        GParam("G param", Vector) = (1, 0, 0, 1)
        BParam("B param", Vector) = (1, 0, 0, 1)
        _ClipValue("AlphaClipThreshold", Float) = 0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
                float3 normal : TEXCOORD1;
            };

            sampler2D _MaskA;
            sampler2D _MaskB;
            sampler2D _LUT;
            float4 RParam;
            float4 GParam;
            float4 BParam;
            float _ClipValue;
                      

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;//TRANSFORM_TEX(v.uv, _MaskA);
                o.normal = v.normal;
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 Holo(half2 uv, float3 normal, half mask, half4 param)
            {
                half viewAngle=dot(_WorldSpaceCameraPos.xyz, normal);
                float2 calc_uv = float2(uv.y*param.x + param.y+viewAngle, param.z);
                return tex2D(_LUT, calc_uv) * mask * param.w;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                half4 maskB = tex2D(_MaskB, i.uv);
                clip(maskB.a - _ClipValue);
                
                half4 maskA = tex2D(_MaskA, i.uv);
                
                half4 holoR = Holo(i.uv, i.normal, maskA.r * maskB.r, RParam);
                half4 holoG = Holo(i.uv, i.normal, maskA.g, GParam);
                half4 holoB = Holo(i.uv, i.normal, maskA.b, BParam);
                
                fixed4 col = half4((holoR+holoG+holoB).rgb, maskB.a);
                return col;
            }
            ENDCG
        }
    }
}

4. 总结与回顾

视角的计算:用sin值也可以表示视角变化,但是点乘用起来很方便,所以用cos

GitHub - MidoriMeng/URP-Hologram-Sticker-Effect

标签:贴纸,normal,half4,sticker,uv,mask,Shader,param,全息
来源: https://blog.csdn.net/weixin_37417198/article/details/122596737

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有