逐顶点的光照: 先看在引擎中的逐顶点和逐像素的光照的效果:

可以發現燈光其實只是作爲一個判斷來使用。最終光照是按頂點還是按像素是根據我們需要來進行組合使用。
FrameDebug中的數據可以明顯看到。多光照下可以隨意自己需要進行設置光照是逐頂點還是逐像素。 在看看Unity提供的MoblieDiffuse


會發現unity提供的這一套shader默認將後續的燈光全部作爲逐頂點來計算光照了。 因爲一些低端電腦或者移動平臺上會出現多盞实时灯光的情况会很少。因此除了主光源外的灯光利用逐顶点计算光照也是可以接受的。
Unity提供的默认standshader:

Unity提供的默认shader有着很丰富的功能。这时就可以完整利用到unity本身提供的灯光设置里的Important和NotImpotant功能。 灯光属性中的Important和NotImpotant的设置对于我们进行shader的灯光计算没有决定性作用,可以根据自己的需要进行书写。Unity的灯光仅作为一个输出数据和判断的数值而已。所有的计算都是在shader内进行的。
注意点: 不建议在一个shader内书写逐顶点和逐像素进行混合运算。除非是项目特殊需求。第一效果不好控制。第二现在平台性能也不会那么差。还是可以方便都用逐像素进行处理的。
逐顶点的shader: ```Shader "Unlit/VertexLight" { Properties {
_Color ("Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Tags{"LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata
{
float4 vertex : POSITION;
fixed3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed3 color : COLOR;
};
float4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float3 diffuse = _Color.rgb * _LightColor0.rgb * saturate(dot(worldNormal,lightDir));
o.color = diffuse + ambient;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed3 col = i.color;
return float4(col,1);
}
ENDCG
}
Pass
{
Name "AddLight"
Tags{"LightMode"="ForwardAdd" }
Blend One One
ZWrite Off
ZTest LEqual
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//==================================
//加入额外光照计算用变体。
//#pragma multi_compile_fwdadd
#pragma multi_compile_fwdadd_fullshadows
//==================================
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
struct appdata
{
float4 vertex : POSITION;
fixed3 normal : NORMAL;
};
struct v2f
{
float4 worldPos : TEXCOORD0;
float4 vertex : SV_POSITION;
fixed3 color : COLOR;
SHADOW_COORDS(3)
};
float4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
#ifdef USING_DIRECTIONAL_LIGHT
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
#else
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - o.worldPos.xyz);
#endif
float3 diffuse = _Color.rgb * _LightColor0.rgb * saturate(dot(worldNormal,worldLightDir));
TRANSFER_SHADOW(o);
UNITY_LIGHT_ATTENUATION(atten, i, o.worldPos.xyz);
o.color = (diffuse + ambient);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed3 col = i.color;
return float4(col,1);
}
ENDCG
}
}
}
逐像素的shader:
```Shader "Unlit/FargmentLight"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
fixed3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 normal : TEXCOORD0;
};
float4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.normal = v.normal;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(i.normal);
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float3 diffuse = _Color.rgb * _LightColor0.rgb * saturate(dot(worldNormal,lightDir));
// sample the texture
fixed3 col = diffuse + ambient;
return float4(col,1);
}
ENDCG
}
Pass
{
Name "AddLight"
Tags{"LightMode"="ForwardAdd" }
Blend One One
ZWrite Off
ZTest LEqual
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//==================================
//加入额外光照计算用变体。
//#pragma multi_compile_fwdadd
#pragma multi_compile_fwdadd_fullshadows
//==================================
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
struct appdata
{
float4 vertex : POSITION;
fixed3 normal : NORMAL;
};
struct v2f
{
float4 worldPos : TEXCOORD0;
float4 vertex : SV_POSITION;
//fixed3 color : COLOR;
fixed3 normal : TEXCOORD1;
SHADOW_COORDS(3)
};
float4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.normal = v.normal;
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
#ifdef USING_DIRECTIONAL_LIGHT
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
#else
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
#endif
fixed3 worldNormal = UnityObjectToWorldNormal(i.normal);
float3 diffuse = _Color.rgb * _LightColor0.rgb * saturate(dot(worldNormal,worldLightDir));
// sample the texture
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos.xyz);
fixed3 col = (diffuse + ambient) * atten;
return float4(col,1);
}
ENDCG
}
}
}
案例工程链接: https://pan.baidu.com/s/17Fh2zRuchHiTQUJUNFSXVWdjQRdSZUMwZr92==?linksource=zhihu&at=1655433478046
文章也发布在知乎:https://zhuanlan.zhihu.com/p/527677672
本文探讨了Unity引擎中逐顶点和逐像素光照的区别,强调了引擎如何根据设备性能灵活选择计算方式,并介绍了Unity默认shader的重要性和灯光设置。还提供了Unlit/VertexLight和Unlit/FragmentLight的Shader示例。
2619

被折叠的 条评论
为什么被折叠?



