Unity 2D 开发小组

创建于:2016-04-22

创建人: indienova

95 信息 1118 成员
讨论 Unity 2D 相关开发内容的小组

2D卡通光照Shader的一些研究

AlsoRowing 2016-11-22

        对2D的光照一直很感兴趣,然后不停的找资料,发现大部分演示都很脏,不够卡通。所以后来就去买了Shader的书,顺便还看到了love2d论坛上的这个帖子https://love2d.org/forums/viewtopic.php?f=5&t=11076,然后就找到了思路。

        素材也是改造自上面那个帖子里的(稍微有点觉得奇怪的是不知道为啥帖子里的生成的法线贴图的G通道是反的,我手动调换了一下灰度变成正的了)。

        光照没有用unity内置的,而是用了一个新的obj跟随鼠标,然后要渲染的物体用脚本获取此obj的坐标赋值给材质。

        

         

        做出来是这个效果的。其中法线贴图和AO贴图我扩大成256x256像素并高斯模糊了,因为如果法线保留原本低像素的话,阴影的锯齿因为不可控所以非常显眼,增加平滑插值又体现不出卡通的味道了,所以只想到这种办法。

        贴图分别是这三张:

        DiffuseMapNormalMap

AOMap



        其中最后一张AO贴图里r通道是AO贴图本身,b通道是为了不被光照影响而重新绘制的黑色勾边。

        Shader的写法是:


Shader "2D_Cel_Shader" {
    Properties {
        _MainTex ("Main Tex", 2D) = "white" {}
        _dark_color ("Dark Color", Color) = (0,0,1,1)
        _light_color ("Light Color", Color) = (1,1,0,1)
        _BumpMap ("Normal Map", 2D) = "bump" {}
        _AOMap ("AO Map", 2D) = "white" {}
        _light_position ("Light Position", Vector) = (0,0,0,0)
}
    SubShader {
        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
        Pass {
            Tags { "LightMode"="ForwardBase" }

            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "Lighting.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _light_color;
            float4 _dark_color;
            sampler2D _BumpMap;
            float4 _BumpMap_ST;
            sampler2D _AOMap;
            float4 _AOMap_ST;
            float4 _light_position;



            struct a2v {
                float4 vertex : POSITION;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float4 uv : TEXCOORD0;
                float2 ao : TEXCOORD1;
                float3 worldpos : TEXCOORD2;
            };

            v2f vert (a2v v) {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

                o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _MainTex_ST.zw;
                o.ao.xy = v.texcoord.xy * _AOMap_ST.xy + _AOMap_ST.zw; 

                o.worldpos = mul(unity_ObjectToWorld, v.vertex).xyz;
                return o;
            }

            float4 frag (v2f i) : SV_Target {
                float4 diffuse = tex2D(_MainTex, i.uv.xy).rgba;
                float3 channels = tex2D(_AOMap, i.ao.xy).rgb;
                float ao = channels.r;
                float bypass = channels.g;

                float3 normal = tex2D(_BumpMap, i.uv.zw).rgb;

                normal = normalize(2*normal-1);
 

                float3 light = float3(0,0,0);

                float3 light_dir = _light_position.xyz - i.worldpos;
                float3 view_dir = normalize(UnityWorldSpaceViewDir(i.worldpos));

                float dist = light_dir.z;
                float atten = smoothstep(60, 30 ,dist);
                light_dir = normalize(light_dir);
                float3 current_light = atten * lerp(0,1,dot(normal, light_dir))*(ao+0.05)*1.2;

                light = max(0,current_light-0.38);

                light *= ao;

                diffuse += tex2D(_MainTex, i.uv.xy).rgba/2 ;

                float3 gooch_light = ( _dark_color * (1 - light)  + _light_color * light * 1.6) * 0.4;


                float3 cel_light = smoothstep(0.1, 0.19, (current_light)/2)  + diffuse.rgb;


                return float4(float3 (( cel_light * diffuse *0.5 + gooch_light) * bypass), diffuse.a); 

            }

            ENDCG
        }
    }
}
        

        这个Shader只是测试了光照的算法,并没有对多光源,Sprites,投影等等事物做调整,无法用于实际项目。


(转发自:原日志地址
 

加入 indienova

  • 建立个人/工作室档案
  • 建立开发中的游戏档案
  • 关注个人/工作室动态
  • 寻找合作伙伴共同开发
  • 寻求线上发行
  • 更多服务……
登录/注册