Shader "Unlit/ForwardBase"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Tags{
"LightMode" = "ForwardBase" //定义该Pass在Unity的流水线中的角色 (只有定义它才能获取到一些Unity内置的光照变量如_LightColor0
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase //只有引入它才能正确进行获取如光照衰减值等信息
#include "UnityCG.cginc"
#include "Lighting.cginc" //这个命名空间中包含_LightColor0
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
col.rgb = col.rgb * _LightColor0.rgb; //_LightColor0是平行光源颜色(即场景自带创建的光源)
return col;
}
ENDCG
}
}
}
假如我去掉
#include "Lighting.cginc"
假如我去掉标签
"LightMode" = "ForwardBase"
没有任何变化,因为Unity工程默认是ForwardBase光照模式!
Edit -> Project Settings -> Graphics,在Graphics面板中设置有渲染路径(也成为光照模式)
同理直接在摄像机指定其他渲染路径,而非Graphics面板设置的
官方文档获知的资料如下(红字为网页翻译,不必太在意后期的文章可能会进行解释)
Forward:前置渲染路径
Deferred : 延迟渲染路径
Legacy Vertex Lit:顶点渲染路径
Legacy Defferred (light prepass):延迟顶点渲染路径
其他特殊的光照模式 :
关于LightMode介绍有另一篇文章说明:https://blog.csdn.net/qq_39574690/article/details/99766585
介绍前向渲染路径原理:(伪代码解释)
Pass{
//遍历模型三角面
for(each primitive in this model)
{
//遍历三角面片元
for(each fragment covered by this primitive){
//深度测试失败
if(failed in depth test){
//抛弃片元,不会进行渲染它
discard;
}else{
//深度测试成功,进行渲染它(Shading可理解是进入了我们的着色器代码,输出的是片元着色器的颜色值)
float4 color = Shading(materialInfo, pos, normal ,lightDir, viewDir);
//将这个颜色,更新到帧缓冲的该片元位置上
writeFrameBuffer(fragment, color);
}
}
}
}
以上伪代码得知,深度测试需要获取深度缓冲区,顺利通过测试后,便进行了计算颜色纸并写入颜色缓冲区。
这个过程是每一个逐像素光源都会进行一次Pass,比如有3个逐像素光源,影响着2个前向渲染路径的物体,就会有3*2=6个Pass进行。每一个Pass可看为一个DC,全部Pass产生的颜色值会进行混合。
在前向渲染路径的ForwardBase模式下,可以针对一个逐像素光源(即默认的平行光)、所有逐顶点光源或SH光源 以及 一个环境光来进行渲染。
光源的Light组件的渲染模式(Render Mode)设置为Not Important的光源会按逐顶点处理或SH处理
渲染模式被设置成Important的光源按逐像素处理
上图为最大的逐顶点个数设置 以及 光源的渲染模式设置
ForwardBase渲染路径有如下的处理(详细情况请参考https://blog.csdn.net/qq_39574690/article/details/99766585)
fixed4 frag (v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 halfDir = normalize(worldLightDir + worldViewDir);
//判断是平行光
#ifdef USING_DIRECTIONAL_LIGHT
//atten是光照衰减值,它是在光照贴图lightmaps中的一个值(Unity自动帮我们处理的)
//如果你没有引入#pragma multi_compile_fwdbase,衰减值可能就是错误的
fixed3 atten = 1.0;//衰减因子为1.0 因为平行光是没有衰减概念的
#endif
//_LightColor0是平行光颜色(一个逐像素光源的颜色)
//下面有_Diffuse和_Specular自发光(材质颜色)和ambient环境光参与
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal, halfDir)), _Gloss);
//环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
return fixed4(ambient + (specular + diffuse) * atten, 1.0);//衰减因子影响的是两个反射的颜色值
}