shader 前向渲染

Unity 渲染路径:
Forward (前向渲染)
Deferred (延迟渲染)
Legacy Vertex Lit
Legacy Deferred

Unity 前向渲染:逐顶点,逐像素处理,球谐函数。
shader 前向渲染

逐像素光源:
1,当光源设置为Import时,是逐像素光源。(不受限制于质量设置里面pixel light count )(Forward Add)
2,光源为auto时,个数在pixel light count 以内的光源都是逐像素光源。(Forward Add)
3,光源为auto时,个数超过pixel light count ,那么按光源对物体影响重要程度排序后,前pixel light count个数的光源为逐像素光源。(Forward Add)
4,最重要的平行光为逐像素光源。(Forward Base)

逐顶点光源:(unity默认要求逐顶点光源不超过4个,超过的按SH光源处理)
1,当光源设置为NotImport时,是逐顶点光源。(Forward Base)
2,超过pixel light count 的光源为逐顶点光源。(Forward Base)

Pass

1,除了设置Pass标签外,还使用了#pragma multi_compile_fwdbase这样的编译指令。只有使用了这样的指令,才可以在相关的pass中得到一些正确的光照变量,例如光照衰减值等。
2,Base Pass中支持一些光照特性,如lightmap。
3,Base Pass中渲染的平行光默认是支持阴影的,而Additional Pass中渲染的光源默认情况下是没有阴影的。可以在additional pass中使用#pragma multi_compile_fwdadd_fullshadows代替#pragma multi_compile_fwdadd来打开阴影。
4,环境光和自发光是在Base Pass中计算的。
5,Additional Pass中开启了混合模式,如果不开启就会替换之前的渲染。通常使用Blend One One。
6,前向渲染一般会定义一个Base Pass(除双面渲染等)以及一个Additional Pass。一个Base Pass仅会执行一次,而一个Additional Pass会根据影响该物体的其他逐像素光源数目被多次调用,即每个逐像素光源会执行一次Additional Pass.

前向渲染补充
1,ForwardAdd这个Pass需要和ForwardBase一起使用,否则会被Unity忽略掉(unity5.x),在新版本中,不会忽略,但是渲染会出错。
2,在Forward和Deferred渲染路径下,Forward的Pass均能被正常渲染。
3,ForwardAdd对每一个逐像素光源都会执行一次Pass,所以不要在ForwardAdd里面计算 unity_4LightPos[x,y,z]0中的数据。会重复计算。

前向渲染shader代码:

Shader "MyShader/001"
{
	Properties
	{
		_Diffuse("diffuse",Color) = (1,1,1,1)
		_Specular("specular",Color) = (1,1,1,1)
		_Gloss("gloss",Range(1,256)) = 20
	}
		SubShader
	{
		Tags { "RenderType" = "Opaque" }
		LOD 100

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

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

			fixed4 _Diffuse;
			fixed4 _Specular;
			float _Gloss;

            struct appdata
            {
                float4 vertex : POSITION;
				float3 normal:NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
				float3 worldNormal:TEXCOORD0;
				float3 worldPos:TEXCOORD1;
				float3 vertexLight : TEXCOORD2;
            };


            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

#ifdef LIGHTMAP_OFF
				float3 shLight = ShadeSH9(float4(v.normal, 1.0));
				o.vertexLight = shLight;
#ifdef VERTEXLIGHT_ON
				float3 vertexLight = Shade4PointLights(
					unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
					unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
					unity_4LightAtten0, o.worldPos, o.worldNormal
				);
				o.vertexLight += vertexLight;
#endif
#endif
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;

				float3 worldNormal = normalize(i.worldNormal);
				float3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);

				fixed3 diffuse = _LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal, worldLightDir));

				fixed3 halfDir = normalize(viewDir + worldLightDir);
				fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(worldNormal, halfDir)), _Gloss);

				return fixed4(ambient + (diffuse + specular)+i.vertexLight, 1);
            }
            ENDCG
        }

		Pass
		{
			Tags{"LightMode"="ForwardAdd"}
			Blend One One

			CGPROGRAM
			#pragma multi_compile_fwdadd
			#pragma vertex vert
			#pragma fragment frag
				 
			#include"UnityCG.cginc"
			#include"Lighting.cginc"
			#include"AutoLight.cginc"

			float4 _Diffuse;
			float4 _Specular;
			float _Gloss;

			struct a2v
			{
				float4 vertex:POSITION;
				float3 normal:NORMAL;
			};

			struct v2f
			{
				float4 vertex:SV_POSITION;
				float3 worldPos:TEXCOORD0;
				float3 worldNormal:TEXCOORD1;
				LIGHTING_COORDS(2, 3)
			};

			v2f vert(a2v v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				TRANSFER_VERTEX_TO_FRAGMENT(o);
				return o;
			}

			fixed4 frag(v2f i):SV_Target
			{
				float3 worldNormal = normalize(i.worldNormal);
				float3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.vertex));

				fixed3 diffuse = _LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal, worldLightDir));

				float3 viewDir = normalize(UnityWorldSpaceViewDir(i.vertex));
				float3 halfDir = normalize(viewDir + worldLightDir);
				fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(worldNormal, halfDir)), _Gloss);
				fixed atten = LIGHT_ATTENUATION(i);
				return fixed4((diffuse + specular)*atten, 1);
			}
			ENDCG
		}
    }
}
shader 前向渲染shader 前向渲染 Unity小林 发布了24 篇原创文章 · 获赞 0 · 访问量 422 私信 关注
上一篇:OpenGL 漫反射辐照度 Diffuse irradiance


下一篇:unity shader 实现blinn-phong光照模型