
前向渲染對(duì)每個(gè)物體每個(gè)光源都需要一個(gè)額外的附加渲染通道,這使得如果燈光變多draw call會(huì)急劇的增加。
在每次前向渲染的過(guò)程中,我們都要轉(zhuǎn)換模型數(shù)據(jù),再進(jìn)行fragmentshader求出光照。這么麻煩,我們?yōu)槭裁床粚缀螖?shù)據(jù)緩存起來(lái)。而這對(duì)于多個(gè)光源的場(chǎng)景來(lái)書(shū)會(huì)節(jié)省很多draw call
1.延遲路徑第一步:填充幾何緩沖區(qū)
struct FragmentOutput{
float4 gBuffer0:SV_TARGET0;
float4 gBuffer1:SV_TARGET1;
float4 gBuffer2:SV_TARGET2;
float4 gBuffer3:SV_TARGET3;
};
1.緩沖區(qū)0
第一個(gè)G緩沖區(qū)用于存儲(chǔ)漫反射率和表面遮擋。這是一個(gè)ARGB32紋理,就像一個(gè)常規(guī)的幀緩沖區(qū)。反射率存儲(chǔ)在RGB通道中,遮擋存儲(chǔ)在A通道中。
finalOutput.gBuffer0.xyz=albedo;
finalOutput.gBuffer0.a=GetAO(i);
2.緩沖區(qū)1
第二個(gè)G緩沖器用于存儲(chǔ)RGB通道中的鏡面高光顏色,以及A通道中的平滑度值。它也是一個(gè)ARGB32紋理。
finalOutput.gBuffer1.xyz=specular;
finalOutput.gBuffer1.a=smoothness;
3.緩沖區(qū)2
第三個(gè)G緩沖區(qū)包含的是世界空間中的法向量。它們存儲(chǔ)在ARGB2101010紋理的RGB通道中。
因?yàn)槲覀冚敵龅闹涤驗(yàn)?-1,而世界坐標(biāo)中法線方向的向量范圍是-1,1。對(duì)此應(yīng)做映射
finalOutput.gBuffer2=float4(normal*0.5+0.5,1.0);
4.緩沖區(qū)3
用于存儲(chǔ)積累的光照,格式分為兩種一種是儲(chǔ)存低動(dòng)態(tài)對(duì)比度的ARGB2101010,另一種存高動(dòng)態(tài)對(duì)比度顏色ARGBHalf;
對(duì)于積累的光照,在寫(xiě)入GBuffer時(shí),應(yīng)加入SH球諧環(huán)境光、和自發(fā)光;
也可以加入反射,或者是在延遲光照的方法考慮進(jìn)去
當(dāng)關(guān)閉HDR時(shí),要將光照進(jìn)行編碼
#pragma multi_compile _ UNITY_HDR_ON
#if !defined(UNITY_HDR_ON)
finalCol=exp2(-finalCol);
#endif
finalOutput.gBuffer3=float4(finalCol,1.0);
GBuffer-shader
Shader"myshader/DeferredMat"{
Properties{
_mainTex("MainTex",2D)="white"{}
_Tine("Time",Color)=(1,1,1,1)
[NoScaleOffset]_MetallicMap("MetallicMap",2D)="black"{}
_Metallic("Metallic",Range(0,1))=0
_Smoothness("smoothness",Range(0,1))=0
[NoScaleOffset]_NormalMap("NormalMap",2D)="Bump"{}
_NormalScale("NormalScale",float)=1
_AoScale("AoScale",Range(0,1))=1
[NoScaleOffset]_EmissionMap("EmissionMap",2D)="black"
}
SubShader{
Tags{"RenderType"="Opaque"}
pass{
Tags{"LightMode"="Deferred"}
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ UNITY_HDR_ON
#include"WriteInGBuffer.cginc"
ENDCG
}
}
Fallback "Diffuse"
}
#if !defined(MY_LIGHTING_INCLUDED)
#define MY_LIGHTING_INCLUDED
#include"UnityPBSLighting.cginc"
#include"AutoLight.cginc"
#include"UnityStandardUtils.cginc"
sampler2D _mainTex;
float4 _mainTex_ST;
float3 _Tine;
sampler2D _MetallicMap;
float _Metallic;
float _Smoothness;
sampler2D _NormalMap;
float _NormalScale;
float _AoScale;
sampler2D _EmissionMap;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
float2 uv:TEXCOORD;
float4 tangent:TANGENT;
};
struct v2f{
float4 pos:SV_POSITION;
float3 worldPos:TEXCOORD0;
float3 normal:TEXCOORD1;
float4 tangent:TEXCOORD2;
float2 uv:TEXCOORD3;
};
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
o.normal=UnityObjectToWorldNormal(v.normal);
o.tangent=float4(UnityObjectToWorldDir(v.tangent.xyz),v.tangent.w);
o.uv=TRANSFORM_TEX(v.uv,_mainTex);
return o;
}
float3 GetAlbedo(v2f i){
return tex2D(_mainTex,i.uv).xyz * _Tine.xyz;
}
float GetMetallic(v2f i){
return tex2D(_MetallicMap,i.uv).r + _Metallic;
}
float GetSmoothness(v2f i){
return _Smoothness;
}
float3 GetNormal(v2f i){
float3 worldNormal=normalize(i.normal);
float3 worldTangent=normalize(i.tangent.xyz);
float3 worldBinormal=cross(worldNormal,worldTangent) * i.tangent.w * unity_WorldTransformParams.w;
float3 tangentNormal=UnpackScaleNormal(tex2D(_NormalMap,i.uv),_NormalScale);
return float3(
tangentNormal.x*worldTangent+
tangentNormal.y*worldBinormal+
tangentNormal.z*worldNormal
);
}
float GetAO(v2f i){
return 1.;
}
UnityLight GetdirLight(v2f i){
UnityLight dirLight;
dirLight.dir=UnityWorldSpaceLightDir(i.worldPos);
UNITY_LIGHT_ATTENUATION(attenuation,i,i.worldPos);
dirLight.color=_LightColor0.xyz * attenuation;
return dirLight;
}
UnityIndirect GetindirLight(v2f i,float3 viewDir){
UnityIndirect indirLight;
indirLight.diffuse=0;
indirLight.specular=0;
indirLight.diffuse-=max(0,ShadeSH9(float4(i.normal,1)));
Unity_GlossyEnvironmentData envData;
envData.roughness = 1 - GetSmoothness(i);
float3 reflectDir=reflect(-viewDir,i.normal);
float3 reflectDir1=BoxProjectedCubemapDirection(reflectDir, i.worldPos,unity_SpecCube0_ProbePosition,unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax);
envData.reflUVW = reflectDir1;
float3 probe0 = Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, envData);
float3 reflectDir2=BoxProjectedCubemapDirection(reflectDir, i.worldPos,unity_SpecCube1_ProbePosition,unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax);
envData.reflUVW = reflectDir2;
float3 probe1= Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1, unity_SpecCube0),unity_SpecCube0_HDR, envData);
indirLight.specular = lerp(probe1, probe0, unity_SpecCube0_BoxMin.w);
float AO = GetAO(i);
indirLight.diffuse*=AO;
indirLight.specular*=AO;
#if defined(UNITY_ENABLE_REFLECTION_BUFFERS)
indirLight.specular=0;
#endif
return indirLight;
}
float3 GetEmission(v2f i){
float3 emission=tex2D(_EmissionMap,i.uv).xyz;
return emission;
}
struct FragmentOutput{
float4 gBuffer0:SV_TARGET0;
float4 gBuffer1:SV_TARGET1;
float4 gBuffer2:SV_TARGET2;
float4 gBuffer3:SV_TARGET3;
};
FragmentOutput frag(v2f i){
float3 albedo=GetAlbedo(i);
float metallic=GetMetallic(i);
float3 specular;
float OneMinuseReflectivity;
albedo = DiffuseAndSpecularFromMetallic(albedo,metallic,specular,OneMinuseReflectivity);
float smoothness=GetSmoothness(i);
float3 normal=GetNormal(i);
float3 viewDir=normalize(UnityWorldSpaceViewDir(i.worldPos));
UnityLight dirLight; //將直接光照設(shè)置為0,
dirLight.dir=float3(0,1,0);
dirLight.color=float3(0,0,0);
UnityIndirect indirLight=GetindirLight(i,viewDir);
fixed3 BRDF=UNITY_BRDF_PBS(albedo,specular,OneMinuseReflectivity,smoothness,normal,viewDir,dirLight,indirLight);
fixed3 emissionCol=GetEmission(i);
fixed3 finalCol=BRDF+emissionCol;
#if !defined(UNITY_HDR_ON)
finalCol=exp2(-finalCol);
#endif
FragmentOutput finalOutput;
finalOutput.gBuffer0.xyz=albedo;
finalOutput.gBuffer0.a=GetAO(i);
finalOutput.gBuffer1.xyz=specular;
finalOutput.gBuffer1.a=smoothness;
finalOutput.gBuffer2=float4(normal*0.5+0.5,1.0);
finalOutput.gBuffer3=float4(finalCol,1.0);
return finalOutput;
}
#endif
二、延遲光照
目前我們已經(jīng)得到4個(gè)緩沖區(qū),現(xiàn)在我們利用這些緩沖區(qū)在lightingshader中計(jì)算燈光
1.deferredLighting中的兩個(gè)Pass
第一個(gè)pass中用來(lái)計(jì)算光照,第二個(gè)pass是,當(dāng)關(guān)閉HDR時(shí),才會(huì)被調(diào)用,用來(lái)將HDR轉(zhuǎn)換為L(zhǎng)DR
SubShader{
pass{
Blend [_SrcBlend] [_DstBlend]
Cull Off
ZTest Always
ZWrite Off
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#pragma exclude_renderers nomrt
#pragma multi_compile_lightpass
#pragma multi_compile _ UNITY_HDR_ON
#include "DeferredLighting.cginc"
ENDCG
}
pass{
Cull off
ZTest Always
ZWrite off
//用蒙版緩沖區(qū)消除對(duì)背景的影響
Stencil{
Ref [_StencilNonBackground]
ReadMask [_StencilNonBackground]
CompBack Equal
CompFront Equal
}
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#pragma exclude_renderers nomrt
#include"UnityCG.cginc"
struct a2v{
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
};
sampler2D _LightBuffer;
v2f vert(a2v v){
v2f o;
o.uv=v.uv;
o.pos=UnityObjectToClipPos(v.vertex);
return o;
}
float4 frag(v2f i):SV_TARGET{
return -log2(tex2D(_LightBuffer,i.uv));
}
ENDCG
}
}
燈光計(jì)算(第一個(gè)pass)
1.讀取G緩沖區(qū)的uv坐標(biāo)
i.pos = UnityObjectToClipPos(v.vertex);
i.uv = ComputeScreenPos(i.pos);
float2 uv = i.uv.xy / i.uv.w;
2.世界坐標(biāo)
normal的法線信息是沿著視角射線的方向的
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
i.ray = v.normal;
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
depth = Linear01Depth(depth);
float3 rayToFarPlane = i.ray * _ProjectionParams.z / i.ray.z;
float3 viewPos = rayToFarPlane * depth;
float3 worldPos = mul(unity_CameraToWorld, float4(viewPos, 1)).xyz;
3.讀取G緩沖數(shù)據(jù)
sampler2D _CameraGBufferTexture0;
sampler2D _CameraGBufferTexture1;
sampler2D _CameraGBufferTexture2;
float3 worldPos = mul(unity_CameraToWorld, float4(viewPos, 1)).xyz;
float3 albedo = tex2D(_CameraGBufferTexture0, uv).rgb;
float3 specularTint = tex2D(_CameraGBufferTexture1, uv).rgb;
float3 smoothness = tex2D(_CameraGBufferTexture1, uv).a;
float3 normal = tex2D(_CameraGBufferTexture2, uv).rgb * 2 - 1;
4.計(jì)算BRDF
float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos);
float3 albedo = tex2D(_CameraGBufferTexture0, uv).rgb;
float3 specularTint = tex2D(_CameraGBufferTexture1, uv).rgb;
float3 smoothness = tex2D(_CameraGBufferTexture1, uv).a;
float3 normal = tex2D(_CameraGBufferTexture2, uv).rgb * 2 - 1;
float oneMinusReflectivity = 1 - SpecularStrength(specularTint);
UnityLight light;
light.color = 0;
light.dir = 0;
UnityIndirect indirectLight;
indirectLight.diffuse = 0;
indirectLight.specular = 0;
float4 color = UNITY_BRDF_PBS(albedo, specularTint, oneMinusReflectivity, smoothness,normal, viewDir, light, indirectLight);
5.平行光燈光參數(shù)
間接燈光在寫(xiě)入GBuffer中時(shí)已經(jīng)加入了,所以indirLight繼續(xù)填0
燈光方向和顏色是從float4 _LightColor, _LightDir 中讀取,注意LightDir為燈光前進(jìn)方向,應(yīng)取反
float4 _LightColor, _LightDir;
UnityLight CreateLight () {
UnityLight light;
light.dir =- _LightDir;
light.color = _LightColor.rgb;
return light;
}
6.平行光陰影+COOKIE
1.依靠AutoLight的宏來(lái)確定由陰影引起的光衰減。 不幸的是,該文件沒(méi)有寫(xiě)入延遲光源。 所以我們自己來(lái)進(jìn)行陰影采樣。陰影貼圖可以通過(guò)_ShadowMapTexture變量來(lái)訪問(wèn)。但是,我們不能隨便聲明這個(gè)變量。 它已經(jīng)為UnityShadowLibrary中被定義點(diǎn)光源和聚光光源的陰影,我們間接導(dǎo)入了它們。 所以我們不應(yīng)該自己定義它,除非使用方向光源的陰影。
2.UnityComputeShadowFadeDistance(worldPos, viewZ) 計(jì)算陰影衰減
UnityComputeShadowFade 計(jì)算衰減距離
#if defined (SHADOWS_SCREEN)
sampler2D _ShadowMapTexture;
#endif
float attenuation = 1;
float shadowAttenuation =1.0;
#if defined(DIRECTIONAL) || defined(DIRECTIONAL_COOKIE)
#if defined(DIRECTIONAL_COOKIE)
float2 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1)).xy;
attenuation *= tex2Dbias(_LightTexture0, float4(uvCookie, 0, -8)).w;
//attenuation *= tex2D(_LightTexture0, uvCookie).w;
#endif
#if defined (SHADOWS_SCREEN)
shadowAttenuation = tex2D(_ShadowMapTexture, uv).r;
float shadowFadeDistance = UnityComputeShadowFadeDistance(worldPos, viewZ);
float shadowFade = UnityComputeShadowFade(shadowFadeDistance);
shadowAttenuation = saturate(shadowAttenuation + shadowFade);
#endif
#else
light.dir = 1;
#endif
light.color = _LightColor.rgb * shadowAttenuation * attenuation;
不要忘記LDR的編碼,像GBuffer寫(xiě)入時(shí) 一樣
#if !defined(UNITY_HDR_ON)
color = exp2(-color);
#endif
7.加入聚光燈
1.金字塔區(qū)域被渲染為一個(gè)常規(guī)的3D對(duì)象。
攝像機(jī)可能會(huì)在聚光光源照亮的體積的內(nèi)部。 甚至可能近平面的一部分都在聚光光源照亮的體積的內(nèi)部,而其余部分位于聚光光源照亮的體積的外部。在這些情況下,模板緩沖區(qū)不能用于限制渲染。
Blend [_SrcBlend] [_DstBlend]
//Cull Off
//ZTest Always
ZWrite Off
2.計(jì)算光源方向
float4 _LightColor, _LightDir, _LightPos;
float3 lightVec = _LightPos.xyz - worldPos;
light.dir = normalize(lightVec);
3.再次計(jì)算世界坐標(biāo)
當(dāng)時(shí)平行光的時(shí)候,_LightAsQuad=1
float _LightAsQuad;
i.ray = lerp(UnityObjectToViewPos(v.vertex) * float3(-1, -1, 1),v.normal,_LightAsQuad);
4.Cookie衰減
_LightTexture0存入Cookie的數(shù)值
float4 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1));
uvCookie.xy /= uvCookie.w;
attenuation *= tex2Dbias(_LightTexture0, float4(uvCookie.xy, 0, -8)).w;
attenuation *= uvCookie.w < 0;
5.距離衰減
聚光光源的光線也會(huì)根據(jù)距離進(jìn)行衰減。該衰減存儲(chǔ)在查找紋理中,可通過(guò)_LightTextureB0獲得。
光源的范圍存儲(chǔ)在_LightPos的第四個(gè)變量中。
使用哪個(gè)紋理通道,因平臺(tái)而異,由UNITY_ATTEN_CHANNEL宏進(jìn)行定義。
sampler2D _LightTexture0, _LightTextureB0;
attenuation *= tex2D(_LightTextureB0,(dot(lightVec, lightVec) * _LightPos.w).rr).UNITY_ATTEN_CHANNEL;
6.陰影
當(dāng)聚光光源有陰影的時(shí)候,會(huì)定義SHADOWS_DEPTH關(guān)鍵字。
#if defined(SHADOWS_DEPTH)
shadowed = true;
#endif
shadowAttenuation = UnitySampleShadowmap(mul(unity_WorldToShadow[0], float4(worldPos, 1)));
8.點(diǎn)光源
與聚光燈原理類似
完整的光源衰減
UnityLight CreateLight (float2 uv, float3 worldPos, float viewZ) {
UnityLight light;
float attenuation = 1;
float shadowAttenuation = 1;
bool shadowed = false;
#if defined(DIRECTIONAL) || defined(DIRECTIONAL_COOKIE)
light.dir = -_LightDir;
#if defined(DIRECTIONAL_COOKIE)
float2 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1)).xy;
attenuation *= tex2Dbias(_LightTexture0, float4(uvCookie, 0, -8)).w;
#endif
#if defined(SHADOWS_SCREEN)
shadowed = true;
shadowAttenuation = tex2D(_ShadowMapTexture, uv).r;
#endif
#else
float3 lightVec = _LightPos.xyz - worldPos;
light.dir = normalize(lightVec);
attenuation *= tex2D(
_LightTextureB0,
(dot(lightVec, lightVec) * _LightPos.w).rr
).UNITY_ATTEN_CHANNEL;
#if defined(SPOT)
float4 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1));
uvCookie.xy /= uvCookie.w;
attenuation *=
tex2Dbias(_LightTexture0, float4(uvCookie.xy, 0, -8)).w;
attenuation *= uvCookie.w < 0;
#if defined(SHADOWS_DEPTH)
shadowed = true;
shadowAttenuation = UnitySampleShadowmap(
mul(unity_WorldToShadow[0], float4(worldPos, 1))
);
#endif
#else
#if defined(POINT_COOKIE)
float3 uvCookie =
mul(unity_WorldToLight, float4(worldPos, 1)).xyz;
attenuation *=
texCUBEbias(_LightTexture0, float4(uvCookie, -8)).w;
#endif
#if defined(SHADOWS_CUBE)
shadowed = true;
shadowAttenuation = UnitySampleShadowmap(-lightVec);
#endif
#endif
#endif
if (shadowed) {
float shadowFadeDistance =
UnityComputeShadowFadeDistance(worldPos, viewZ);
float shadowFade = UnityComputeShadowFade(shadowFadeDistance);
shadowAttenuation = saturate(shadowAttenuation + shadowFade);
#if defined(UNITY_FAST_COHERENT_DYNAMIC_BRANCHING) && defined(SHADOWS_SOFT)
UNITY_BRANCH
if (shadowFade > 0.99) {
shadowAttenuation = 1;
}
#endif
}
light.color = _LightColor.rgb * (attenuation * shadowAttenuation);
return light;
}
完整光照計(jì)算Shader
Shader "Custom/DeferredShading" {
Properties {
}
SubShader {
Pass {
Blend [_SrcBlend] [_DstBlend]
ZWrite Off
CGPROGRAM
#pragma target 3.0
#pragma vertex VertexProgram
#pragma fragment FragmentProgram
#pragma exclude_renderers nomrt
#pragma multi_compile_lightpass
#pragma multi_compile _ UNITY_HDR_ON
#include "MyDeferredShading.cginc"
ENDCG
}
Pass {
Cull Off
ZTest Always
ZWrite Off
Stencil {
Ref [_StencilNonBackground]
ReadMask [_StencilNonBackground]
CompBack Equal
CompFront Equal
}
CGPROGRAM
#pragma target 3.0
#pragma vertex VertexProgram
#pragma fragment FragmentProgram
#pragma exclude_renderers nomrt
#include "UnityCG.cginc"
sampler2D _LightBuffer;
struct VertexData {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct Interpolators {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
Interpolators VertexProgram (VertexData v) {
Interpolators i;
i.pos = UnityObjectToClipPos(v.vertex);
i.uv = v.uv;
return i;
}
float4 FragmentProgram (Interpolators i) : SV_Target {
return -log2(tex2D(_LightBuffer, i.uv));
}
ENDCG
}
}
}
#if !defined(MY_DEFERRED_SHADING)
#define MY_DEFERRED_SHADING
#include "UnityPBSLighting.cginc"
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
sampler2D _CameraGBufferTexture0;
sampler2D _CameraGBufferTexture1;
sampler2D _CameraGBufferTexture2;
#if defined(POINT_COOKIE)
samplerCUBE _LightTexture0;
#else
sampler2D _LightTexture0;
#endif
sampler2D _LightTextureB0;
float4x4 unity_WorldToLight;
#if defined (SHADOWS_SCREEN)
sampler2D _ShadowMapTexture;
#endif
float4 _LightColor, _LightDir, _LightPos;
float _LightAsQuad;
struct VertexData {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct Interpolators {
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float3 ray : TEXCOORD1;
};
UnityLight CreateLight (float2 uv, float3 worldPos, float viewZ) {
UnityLight light;
float attenuation = 1;
float shadowAttenuation = 1;
bool shadowed = false;
#if defined(DIRECTIONAL) || defined(DIRECTIONAL_COOKIE)
light.dir = -_LightDir;
#if defined(DIRECTIONAL_COOKIE)
float2 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1)).xy;
attenuation *= tex2Dbias(_LightTexture0, float4(uvCookie, 0, -8)).w;
#endif
#if defined(SHADOWS_SCREEN)
shadowed = true;
shadowAttenuation = tex2D(_ShadowMapTexture, uv).r;
#endif
#else
float3 lightVec = _LightPos.xyz - worldPos;
light.dir = normalize(lightVec);
attenuation *= tex2D(
_LightTextureB0,
(dot(lightVec, lightVec) * _LightPos.w).rr
).UNITY_ATTEN_CHANNEL;
#if defined(SPOT)
float4 uvCookie = mul(unity_WorldToLight, float4(worldPos, 1));
uvCookie.xy /= uvCookie.w;
attenuation *=
tex2Dbias(_LightTexture0, float4(uvCookie.xy, 0, -8)).w;
attenuation *= uvCookie.w < 0;
#if defined(SHADOWS_DEPTH)
shadowed = true;
shadowAttenuation = UnitySampleShadowmap(
mul(unity_WorldToShadow[0], float4(worldPos, 1))
);
#endif
#else
#if defined(POINT_COOKIE)
float3 uvCookie =
mul(unity_WorldToLight, float4(worldPos, 1)).xyz;
attenuation *=
texCUBEbias(_LightTexture0, float4(uvCookie, -8)).w;
#endif
#if defined(SHADOWS_CUBE)
shadowed = true;
shadowAttenuation = UnitySampleShadowmap(-lightVec);
#endif
#endif
#endif
if (shadowed) {
float shadowFadeDistance =
UnityComputeShadowFadeDistance(worldPos, viewZ);
float shadowFade = UnityComputeShadowFade(shadowFadeDistance);
shadowAttenuation = saturate(shadowAttenuation + shadowFade);
#if defined(UNITY_FAST_COHERENT_DYNAMIC_BRANCHING) && defined(SHADOWS_SOFT)
UNITY_BRANCH
if (shadowFade > 0.99) {
shadowAttenuation = 1;
}
#endif
}
light.color = _LightColor.rgb * (attenuation * shadowAttenuation);
return light;
}
Interpolators VertexProgram (VertexData v) {
Interpolators i;
i.pos = UnityObjectToClipPos(v.vertex);
i.uv = ComputeScreenPos(i.pos);
i.ray = lerp(
UnityObjectToViewPos(v.vertex) * float3(-1, -1, 1),
v.normal,
_LightAsQuad
);
return i;
}
float4 FragmentProgram (Interpolators i) : SV_Target {
float2 uv = i.uv.xy / i.uv.w;
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
depth = Linear01Depth(depth);
float3 rayToFarPlane = i.ray * _ProjectionParams.z / i.ray.z;
float3 viewPos = rayToFarPlane * depth;
float3 worldPos = mul(unity_CameraToWorld, float4(viewPos, 1)).xyz;
float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos);
float3 albedo = tex2D(_CameraGBufferTexture0, uv).rgb;
float3 specularTint = tex2D(_CameraGBufferTexture1, uv).rgb;
float3 smoothness = tex2D(_CameraGBufferTexture1, uv).a;
float3 normal = tex2D(_CameraGBufferTexture2, uv).rgb * 2 - 1;
float oneMinusReflectivity = 1 - SpecularStrength(specularTint);
UnityLight light = CreateLight(uv, worldPos, viewPos.z);
UnityIndirect indirectLight;
indirectLight.diffuse = 0;
indirectLight.specular = 0;
float4 color = UNITY_BRDF_PBS(
albedo, specularTint, oneMinusReflectivity, smoothness,
normal, viewDir, light, indirectLight
);
#if !defined(UNITY_HDR_ON)
color = exp2(-color);
#endif
return color;
}
#endif