Unity SDF贴图的应用,手把手教你写出可以正确计算并且渲染出二次元角色面部阴影的着色器(含代码,图片说明和原理)

梦开始的地方

近年来卡通风格渲染的游戏越来越多,三渲二这个的出现频率也越来越高

无论是去年提名TGA年度最佳移动端游戏的《崩坏:星穹铁道》还是风靡全球的《原神》,他们都是卡通渲染风格的游戏,也都运用到了三渲二相关技术

原神

 不知道你是否和我一样跃跃欲试,想写出一个三渲二风格的shader。

说干就干,不知道您是不是这样想的,所谓三渲二,不就是亮面一个颜色,暗面一个颜色,有明显的明暗交界线吗?简单!

计算一个像素的法向量与光的法向量夹角,诺大于90度,则这个像素位于暗面,反之则位于亮面

我们便可以写出一个简单的shader(以unity的CG语言为例)

//这个shader只是个入门级示例shader,游戏公司的shader比这个复杂很多
Shader "CelShader/CelShaderWithTex"
{
    Properties
    {
        _Darklight("Dark Light",Color) = (0.1,0.1,0.1,1)
        _MainTex("Main Tex",2D) = "white"{}
    }
    SubShader
    {
         



        Pass
        {
            Tags{"LightMode" = "ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog

            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            float3 _Darklight;
            sampler2D _MainTex;
            struct c2v
            {
                float4 vertex:POSITION;
                float3 normal:NORMAL;
                float2 uv:TEXCOORD0;
            };

            struct v2f
            {
                float4 pos:SV_POSITION;
                float3 worldNormal:NORMAL;
                float2 uv:TEXCOORD;
                float3 objViewDir:COLOR1;
                float3 normal:NORMAL2;
            };

            v2f vert(c2v input)
            {
                v2f output;
                output.pos = UnityObjectToClipPos(input.vertex);
                output.worldNormal = normalize( mul((float3x3)unity_ObjectToWorld,input.normal) );
                output.uv = input.uv;


                float3 ObjViewDir = normalize(ObjSpaceViewDir(input.vertex));
                output.objViewDir = ObjViewDir;
                output.normal = normalize(input.normal);

                return output;
            }


            fixed3 frag(in v2f input):SV_TARGET0
            {
                fixed3 diffuseColor = _LightColor0.rgb *  tex2D(_MainTex, input.uv).rgb ;
                fixed3 col = UNITY_LIGHTMODEL_AMBIENT.xyz + diffuseColor;
                
                
                
                fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);


                if(dot(input.worldNormal,worldLightDir)<0)
                {
                    return col * _Darklight;
                }
                return col;
            }

            
            ENDCG
        }
    }
    FallBack "Diffuse"
}


//LZX completed this shader in 2024/04/04

当然了,在shader实战中我们应该尽量避免if(因为显卡不擅长逻辑判断,显卡擅长的是浮点运算)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想换电脑的LoongLy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值