1.前向渲染
(1)
Shader "Unlit/001"
{
Properties
{
_MainTex("Main Tex", 2D) = "white"{} // 纹理贴图
_Diffuse("Diffuse",Color) = (1,1,1,1)
_Specular("Specular", Color) = (1,1,1,1)
_Gloss("Gloss", Range(8.0, 256)) = 20
}
//前向渲染路径原理:渲染对象的渲染图元,并计算两个缓冲区(深度与颜色缓冲区)。深度决定片元是否可见。可见则更新颜色缓冲区颜色值
//对每个逐像素光照,都要进行一次上述的过程。若物体被多个逐像素光照影响,则物体执行多个pass,每个物体执行一次逐像素光照计算。
//N个物体M个逐像素光照,N*M个pass
//Base pass不仅可以处理逐像素光照,还可以处理其他。如逐顶点光照,球鞋函数。
//前向渲染有两种pass。一个是BasePass,一个AdditionPass
//BasePass计算最主要的平行光(最亮的,没有则不处理。只有这个光逐像素处理),环境光,自发光。逐顶点/SH光源和Lightmaps.默认支持阴影。 只会执行一次。
//AdditionPass计算额外的逐像素光源,每个pass对应一个光源。这里的光源类型不定,但一定是逐像素。
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass {//前向渲染中Base Pass
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma multi_compile_fwdbase
//这个指令可以保证我们在shder中使用光照衰减等光照变量可以被正确赋值
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
sampler2D _MainTex;
float4 _MainTex_ST;
struct a2v
{
float4 vertex : POSITION;
float3 normal:NORMAL;
float4 texcoord:TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos:TEXCOORD1;
float2 uv : TEXCOORD2;
float3 vertexLight : TEXCOORD3;//顶点光照与球鞋光照
};
v2f vert (a2v v)
{
v2f f;
f.vertex = UnityObjectToClipPos(v.vertex);
f.worldNormal = UnityObjectToWorldNormal(v.normal);
f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
f.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
//下面是顶点光源与球鞋光源的计算
#ifdef LIGHTMAP_OFF
// LIGHTMAP关闭才会计算球鞋,顶点光照
float3 shLight = ShadeSH9(float4(v.normal,0.3));//球鞋光源。传入法线。
f.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, f.worldPos, f.worldNormal);
f.vertexLight += vertexLight;
#endif
#endif
return f;
}
fixed4 frag (v2f i) : SV_Target
{
//然后在Base Pass中处理场景中的最重要的平行光
//如果场景中包含了多个平行光,
//Unity会选择最亮的平行光传递给Base Pass进行逐像素处理,
//其他平行光会按照逐顶点或在Additional Pass中按逐像素的方式处理。
//_LightColor0得到平行光强度
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 albedo =tex2D(_MainTex,i.uv).rgb* _Diffuse.rgb;
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT*albedo;
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal,worldLightDir))*albedo;
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
//fixed3 viewDir = normalize(UnityWorldSpaceViewDir(f.WorldPos));
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(worldNormal,halfDir)),_Gloss);
return fixed4(ambient + diffuse + specular + i.vertexLight, 1);
}
ENDCG
}
Pass//前向渲染中Additional Pass
{
Tags{"LightMode" = "ForwardAdd"}
Blend One One
//开启并设置混合模式。光照是混合而非覆盖。(还可以换成其他混合模式)
CGPROGRAM
#pragma multi_compile_fwdadd
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "AutoLight.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v
{
float4 vertex:POSITION;
float3 normal :NORMAL;
};
struct v2f
{
float4 pos :SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
LIGHTING_COORDS(2,3)//与光照衰减相关。2,3分别指TEXCOORD2,3
};
v2f vert(a2v v)
{
v2f f;
f.pos = UnityObjectToClipPos(v.vertex);
f.worldNormal = UnityObjectToWorldNormal(v.normal);
f.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
TRANSFER_VERTEX_TO_FRAGMENT(f);
return f;
}
fixed4 frag(v2f f):SV_Target
{
fixed3 worldNormal = normalize(f.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(f.worldPos));
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0,dot(worldNormal,worldLightDir));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(f.worldPos));
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(viewDir,halfDir)),_Gloss);
fixed atten = LIGHT_ATTENUATION(f);//计算衰减。已经为不同类型光源做出适应
return fixed4((diffuse+ specular)*atten,1.0);
}
ENDCG
}
}
}
(2)
//最基础功能:Base中接收平行光环境光,add里接收其他逐像素光源并计算衰减(base里没有添加顶点光源与球鞋光源处理)
Shader "09-1" {
Properties {
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
_Specular ("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
SubShader {
Tags { "RenderType"="Opaque" }
//Base Pass
Pass {
// Pass for ambient light & first pixel light (directional light)
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
//保证在Shader中使用光照衰减等变量可以被正确赋值
#pragma multi_compile_fwdbase
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};
v2f vert(a2v v) {
v2f f;
f.pos = UnityObjectToClipPos(v.vertex);
f.worldNormal = UnityObjectToWorldNormal(v.normal);
f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return f;
}
fixed4 frag(v2f i) : SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
//_WorldSpaceLightPos0得到平行光方向
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
//Base Pass计算环境光
//只计算一次即可
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
//然后在Base Pass中处理场景中的最重要的平行光
//如果场景中包含了多个平行光,
//Unity会选择最亮的平行光传递给Base Pass进行逐像素处理,
//其他平行光会按照逐顶点或在Additional Pass中按逐像素的方式处理。
//_LightColor0得到平行光强度
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
//令平行光衰减值为1
fixed atten = 1.0;
return fixed4(ambient + (diffuse + specular) * atten, 1.0);
}
ENDCG
}
//Additional Pass
Pass {
// Pass for other pixel lights
Tags { "LightMode"="ForwardAdd" }
//使用Blend命令开启和设置混合模式
//实现Additional Pass计算得到的光照结果在帧缓存中与之前的光照结果进行叠加
Blend One One
CGPROGRAM
//保证在Shader中使用光照衰减等变量可以被正确赋值
#pragma multi_compile_fwdadd
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "AutoLight.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
//判断当前处理的逐像素光源的类型
#ifdef USING_DIRECTIONAL_LIGHT
//如果是平行光,光源方向可以直接得到
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
#else
//如果是点光源或聚光灯,
//光源方向需要用这个位置减去世界空间下的顶点位置。
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
#endif
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
//处理不同光源的衰减
#ifdef USING_DIRECTIONAL_LIGHT
fixed atten = 1.0;
#else
#if defined (POINT)
//点光
float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
//使用宏UN1TY_ATTEN_CHANNEL来得到衰减纹理中衰减值所在的分量
#elif defined (SPOT)
//聚光
float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w
* tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#else
fixed atten = 1.0;
#endif
#endif
return fixed4((diffuse + specular) * atten, 1.0);
}
ENDCG
}
}
FallBack "Specular"
}
(3)
//接收来自平行光的阴影
Shader "09-2" {
Properties {
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
_Specular ("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
SubShader {
Tags { "RenderType"="Opaque" }
//Base Pass
Pass {
// Pass for ambient light & first pixel light (directional light)
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma multi_compile_fwdbase
//保证在Shader中使用光照衰减等变量可以被正确赋值
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "AutoLight.cginc"
//该文件声明计算阴影时用的宏
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
SHADOW_COORDS(2)
//添加内置宏,用于声明一个用于对阴影纹理采样的坐标。
//由于已经占用了2个插值寄存器,
//因此传入的参数是2,阴影纹理坐标将占用第三个寄存器。
};
v2f vert(a2v v) {
v2f f;
f.pos = UnityObjectToClipPos(v.vertex);
f.worldNormal = UnityObjectToWorldNormal(v.normal);
f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
TRANSFER_SHADOW(f);//计算v2f中声明的阴影纹理坐标
return f;
}
fixed4 frag(v2f i) : SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
//_WorldSpaceLightPos0得到平行光方向
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
//Base Pass计算环境光
//只计算一次即可
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed shadow = SHADOW_ATTENUATION(i);//使用阴影坐标对阴影贴图进行采样
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir))* shadow;
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss)* shadow;//最后乘上阴影值shadow
//令平行光衰减值为1
fixed atten = 1.0;
return fixed4(ambient + (diffuse + specular) * atten, 1.0);
}
ENDCG
}
//Additional Pass
Pass {
// Pass for other pixel lights
Tags { "LightMode"="ForwardAdd" }
//使用Blend命令开启和设置混合模式
//实现Additional Pass计算得到的光照结果在帧缓存中与之前的光照结果进行叠加
Blend One One
CGPROGRAM
//保证在Shader中使用光照衰减等变量可以被正确赋值
#pragma multi_compile_fwdadd
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "AutoLight.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
//判断当前处理的逐像素光源的类型
#ifdef USING_DIRECTIONAL_LIGHT
//如果是平行光,光源方向可以直接得到
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
#else
//如果是点光源或聚光灯,
//光源方向需要用这个位置减去世界空间下的顶点位置。
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
#endif
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
//处理不同光源的衰减
#ifdef USING_DIRECTIONAL_LIGHT
fixed atten = 1.0;
#else
#if defined (POINT)
//点光
float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
//使用宏UN1TY_ATTEN_CHANNEL来得到衰减纹理中衰减值所在的分量
#elif defined (SPOT)
//聚光
float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w
* tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#else
fixed atten = 1.0;
#endif
#endif
return fixed4((diffuse + specular) * atten, 1.0);
}
ENDCG
}
}
FallBack "Specular"
}
//统一管理衰减与阴影
Shader "09-3" {
Properties {
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
_Specular ("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
SubShader {
Tags { "RenderType"="Opaque" }
//Base Pass
Pass {
// Pass for ambient light & first pixel light (directional light)
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma multi_compile_fwdbase
//保证在Shader中使用光照衰减等变量可以被正确赋值
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "AutoLight.cginc"
//该文件声明计算阴影时用的宏
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
SHADOW_COORDS(2)
//添加内置宏,用于声明一个用于对阴影纹理采样的坐标。
//由于已经占用了2个插值寄存器,
//因此传入的参数是2,阴影纹理坐标将占用第三个寄存器。
};
v2f vert(a2v v) {
v2f f;
f.pos = UnityObjectToClipPos(v.vertex);
f.worldNormal = UnityObjectToWorldNormal(v.normal);
f.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
TRANSFER_SHADOW(f);//计算v2f中声明的阴影纹理坐标
return f;
}
fixed4 frag(v2f i) : SV_Target {
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
//用于计算光照衰减和阴影的宏,
//第一个参数用于存储将光照衰减和阴影值相乘后的结果。
//第二个参数是结构体v2f,这个参数会传递给SHADOW_ATTENUATION,用来计算阴影值。
//第三个参数是世界空间的坐标,用于计算光源空间下的坐标,再对光照衰减纹理釆样来得到光照衰减。
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
return fixed4(ambient + (diffuse + specular) * atten, 1.0);
}
ENDCG
}
//Additional Pass
Pass {
// Pass for other pixel lights
Tags { "LightMode"="ForwardAdd" }
//使用Blend命令开启和设置混合模式
//实现Additional Pass计算得到的光照结果在帧缓存中与之前的光照结果进行叠加
Blend One One
CGPROGRAM
//保证在Shader中使用光照衰减等变量可以被正确赋值
#pragma multi_compile_fwdadd
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "AutoLight.cginc"
//该文件声明计算阴影时用的宏
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
SHADOW_COORDS(2)
//添加内置宏,用于声明一个用于对阴影纹理采样的坐标。
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}
fixed4 frag(v2f i) : SV_Target {
//fixed3 worldNormal = normalize(i.worldNormal);
判断当前处理的逐像素光源的类型
//#ifdef USING_DIRECTIONAL_LIGHT
// //如果是平行光,光源方向可以直接得到
// fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
//#else
// //如果是点光源或聚光灯,
// //光源方向需要用这个位置减去世界空间下的顶点位置。
// fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
//#endif
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
处理不同光源的衰减
//#ifdef USING_DIRECTIONAL_LIGHT
// fixed atten = 1.0;
//#else
// #if defined (POINT)
// //点光
// float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
// fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
// //使用宏UN1TY_ATTEN_CHANNEL来得到衰减纹理中衰减值所在的分量
// #elif defined (SPOT)
// //聚光
// float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
// fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w
// * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
// #else
// fixed atten = 1.0;
// #endif
//#endif
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
return fixed4((diffuse + specular)* atten, 1.0);
}
ENDCG
}
}
FallBack "Specular"
}
2.延迟渲染
Shader "Unlit/002"
{
Properties
{
_MainTex("Texture",2D) = "white" {}
_Diffuse("Diffuse",Color) = (1,1,1,1)
_Specular("Specular", Color) = (1,1,1,1)
_Gloss("Gloss", Range(8.0, 50)) = 20
}
//延迟渲染主要包含了两个Pass。
//在第一个Pass中,我们不进行任何光照计算,而是仅仅计算哪些片元是可见的,这主要是通过深度缓冲技术来实现
//当发现一个片元是可见的,我们就把它的相关信息存储到G缓冲区中。
//然后,在第二个Pass中,我们利用G缓冲区的各个片元信息进行真正的光照计算。
//不支持真正的抗锯齿(anti-aliasing)功能。
//不能处理半透明物体。
//对显卡有一定要求。如果要使用延迟渲染的话,显卡必须支持MRT (Multiple Render Targets)、Shader Mode 3.0及以上、深度渲染纹理以及双面的模板缓冲。
//伪代码
//Pass1
//{
// //第一个Pass不进行真正的光照计算
// //仅仅把光照计算需要的信息存储到G缓冲中
// for (each primitive in this model)
// {
// for (each fragment covered by this primitive)
// {
// if(failed in depth test)
// {
// discard;
// }
// else
// {
// //如果该片元可见
// //就把需要的信息存储到G缓冲中
// writeGBuffer(materialInfo,pos,normal,lightDir,viewDir);
// }
// }
// }
//}
//Pass2
//{
// //利用G缓冲中的信息进行真正的光照计算
// for(each pixel in the screen)
// {
// if(the pixel is valid)
// {
// //如果该像素是有效的
// //读取它对应的G缓冲中的信息
// readGBuffer(pixel,materialInfo,pos,normal,lightDir,viewDir);
// //根据读到的信息进行光照计算
// float4 color = Shading(materialInfo,pos,normal,lightDir,viewDir);
// //更新帧缓冲
// writeFrameBuffer(pixel,color);
// }
// }
//}
SubShader
{
Tags { "RenderType" = "Opaque" }
LOD 100
Pass
{
Tags{"LightMode" = "Deferred"}
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#pragma exclude_renderers norm
#pragma multi_compile __ UNITY_HDR_ON
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct appdata
{
float4 vertex :POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f
{
float2 uv: TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldNormal : TEXCOORD1;
float3 worldPos : TEXCOORD2;
};
struct DeferredOutput
{
float4 gBuffer0 : SV_TARGET0;
float4 gBuffer1 : SV_TARGET1;
float4 gBuffer2 : SV_TARGET2;
float4 gBuffer3 : SV_TARGET3;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv,_MainTex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}
DeferredOutput frag(v2f i)
{
DeferredOutput o;
fixed3 color = tex2D(_MainTex, i.uv).rgb * _Diffuse.rgb;
o.gBuffer0.rgb = color;
o.gBuffer0.a = 1;
o.gBuffer1.rgb = _Specular.rgb;
o.gBuffer1.a = _Gloss/50.0;
o.gBuffer2 = float4(i.worldNormal * 0.5 + 0.5,1);
#if !defined(UNITY_HDR_ON)
color.rgb = exp2(-color.rgb);
#endif
o.gBuffer3 = fixed4(color,1);
return o;
}
ENDCG
}
}
}