2d shader unity 阴影_2D卡通光照Shader的一些研究

本文探讨了在Unity中创建2D卡通光照Shader的过程,通过改造素材和自定义Shader来实现独特的阴影效果。作者使用独立的光源对象、自定义脚本和法线贴图来模拟光照,并分享了Shader代码示例,尽管目前仅适用于单光源,不支持多光源和Sprites的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

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

贴图分别是这三张:

其中最后一张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,投影等等事物做调整,无法用于实际项目。

(转发自:原日志地址)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值