|
|
|
|
|
|
|
|
|
|
void DefineSurface(VertOutput i, inout SurfacePBR o); |
|
|
|
|
|
|
|
half3 MetallicSetup(float2 uv, SurfacePBR s, out half3 specular, out half smoothness, out half oneMinusReflectivity) |
|
|
|
half3 MetallicSetup(float2 uv, float3 albedo, float metallic, out half3 specular, out half oneMinusReflectivity) |
|
|
|
smoothness = s.Smoothness;// metallicGloss.g; |
|
|
|
|
|
|
|
// We'll need oneMinusReflectivity, so |
|
|
|
// 1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) = lerp(1-dielectricSpec, 0, metallic) |
|
|
|
// store (1-dielectricSpec) in unity_ColorSpaceDielectricSpec.a, then |
|
|
|
// 1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) = |
|
|
|
// = alpha - metallic * alpha |
|
|
|
// We'll need oneMinusReflectivity, so |
|
|
|
// 1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) = lerp(1-dielectricSpec, 0, metallic) |
|
|
|
// store (1-dielectricSpec) in unity_ColorSpaceDielectricSpec.a, then |
|
|
|
// 1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) = |
|
|
|
// = alpha - metallic * alpha |
|
|
|
oneMinusReflectivity = oneMinusDielectricSpec - s.Metallic * oneMinusDielectricSpec; |
|
|
|
specular = lerp(_DieletricSpec.rgb, s.Albedo, s.Metallic); |
|
|
|
oneMinusReflectivity = oneMinusDielectricSpec - metallic * oneMinusDielectricSpec; |
|
|
|
specular = lerp(_DieletricSpec.rgb, albedo, metallic); |
|
|
|
return s.Albedo * oneMinusReflectivity; |
|
|
|
return albedo * oneMinusReflectivity; |
|
|
|
half3 SpecularSetup(float2 uv, SurfacePBR s, out half3 specular, out half smoothness, out half oneMinusReflectivity) |
|
|
|
half3 SpecularSetup(float2 uv, half3 albedo, half3 specColor, out half3 specular, out half oneMinusReflectivity) |
|
|
|
half4 specGloss = float4(s.Specular, s.Smoothness); |
|
|
|
specular = specGloss.rgb; |
|
|
|
smoothness = specGloss.a; |
|
|
|
oneMinusReflectivity = 1.0h - SpecularReflectivity(specular); |
|
|
|
return s.Albedo * (half3(1, 1, 1) - specular); |
|
|
|
specular = specColor; |
|
|
|
oneMinusReflectivity = 1.0h - SpecularReflectivity(specColor); |
|
|
|
return albedo * (half3(1, 1, 1) - specColor); |
|
|
|
half4 LightweightFragmentPBR(VertOutput i) : SV_Target |
|
|
|
half4 FragmentLightingPBR(float4 uv, float4 posWS, float3 normal, float3 tangent, float3 binormal, float4 viewDir, float4 fogCoord, |
|
|
|
float3 albedo, float metallic, float3 specular, float smoothness, float3 normalMap, float occlusion, float3 emission, float alpha) |
|
|
|
SurfacePBR o = InitializeSurfacePBR(); |
|
|
|
DefineSurface(i, o); |
|
|
|
|
|
|
|
//float2 uv = i.mesUV0.xy; |
|
|
|
float2 lightmapUV = i.meshUV0.zw; |
|
|
|
float2 lightmapUV = uv.zw; |
|
|
|
half3 specColor; |
|
|
|
half smoothness; |
|
|
|
half oneMinusReflectivity; |
|
|
|
half3 specColor; |
|
|
|
half oneMinusReflectivity; |
|
|
|
half3 diffColor = MetallicSetup(i.meshUV0.xy, o, specColor, smoothness, oneMinusReflectivity); |
|
|
|
half3 diffColor = MetallicSetup(uv.xy, albedo, metallic, specColor, oneMinusReflectivity); |
|
|
|
half3 diffColor = SpecularSetup(i.meshUV0.xy, o, specColor, smoothness, oneMinusReflectivity); |
|
|
|
half3 diffColor = SpecularSetup(uv.xy, albedo, specular, specColor, oneMinusReflectivity); |
|
|
|
diffColor = PreMultiplyAlpha(diffColor, o.Alpha, oneMinusReflectivity, /*out*/ o.Alpha); |
|
|
|
diffColor = PreMultiplyAlpha(diffColor, alpha, oneMinusReflectivity, /*out*/ alpha); |
|
|
|
// Roughness is (1.0 - smoothness)² |
|
|
|
half perceptualRoughness = 1.0h - smoothness; |
|
|
|
// Roughness is (1.0 - smoothness)² |
|
|
|
half perceptualRoughness = 1.0h - smoothness; |
|
|
|
half3 normal; |
|
|
|
half3 norm; |
|
|
|
half3 tangentToWorld0 = half3(i.tangent.x, i.binormal.x, i.normal.x); |
|
|
|
half3 tangentToWorld1 = half3(i.tangent.y, i.binormal.y, i.normal.y); |
|
|
|
half3 tangentToWorld2 = half3(i.tangent.z, i.binormal.z, i.normal.z); |
|
|
|
normal = normalize(half3(dot(o.Normal, tangentToWorld0), dot(o.Normal, tangentToWorld1), dot(o.Normal, tangentToWorld2))); |
|
|
|
half3 tangentToWorld0 = half3(tangent.x, binormal.x, normal.x); |
|
|
|
half3 tangentToWorld1 = half3(tangent.y, binormal.y, normal.y); |
|
|
|
half3 tangentToWorld2 = half3(tangent.z, binormal.z, normal.z); |
|
|
|
norm = normalize(half3(dot(normalMap, tangentToWorld0), dot(normalMap, tangentToWorld1), dot(normalMap, tangentToWorld2))); |
|
|
|
normal = normalize(i.normal); |
|
|
|
norm = normalize(normal); |
|
|
|
// TODO: shader keyword for occlusion |
|
|
|
// TODO: Reflection Probe blend support. |
|
|
|
half3 reflectVec = reflect(-i.viewDir.xyz, normal); |
|
|
|
// TODO: shader keyword for occlusion |
|
|
|
// TODO: Reflection Probe blend support. |
|
|
|
half3 reflectVec = reflect(viewDir.xyz, norm); |
|
|
|
UnityIndirect indirectLight = LightweightGI(lightmapUV, i.fogCoord.yzw, reflectVec, o.Occlusion, perceptualRoughness); |
|
|
|
UnityIndirect indirectLight = LightweightGI(lightmapUV, fogCoord.yzw, reflectVec, occlusion, perceptualRoughness); |
|
|
|
// PBS |
|
|
|
// grazingTerm = F90 |
|
|
|
half grazingTerm = saturate(smoothness + (1 - oneMinusReflectivity)); |
|
|
|
half fresnelTerm = Pow4(1.0 - saturate(dot(normal, i.viewDir.xyz))); |
|
|
|
half3 color = LightweightBRDFIndirect(diffColor, specColor, indirectLight, perceptualRoughness * perceptualRoughness, grazingTerm, fresnelTerm); |
|
|
|
half3 lightDirection; |
|
|
|
// PBS |
|
|
|
// grazingTerm = F90 |
|
|
|
half grazingTerm = saturate(smoothness + (1 - oneMinusReflectivity)); |
|
|
|
half fresnelTerm = Pow4(1.0 - saturate(dot(norm, viewDir.xyz))); |
|
|
|
half3 color = LightweightBRDFIndirect(diffColor, specColor, indirectLight, perceptualRoughness * perceptualRoughness, grazingTerm, fresnelTerm); |
|
|
|
half3 lightDirection; |
|
|
|
half3 vertexNormal = half3(tangentToWorld0.z, tangentToWorld1.z, tangentToWorld2.z); // Fix this |
|
|
|
half3 vertexNormal = half3(tangentToWorld0.z, tangentToWorld1.z, tangentToWorld2.z); |
|
|
|
half3 vertexNormal = i.normal; |
|
|
|
half3 vertexNormal = normal; |
|
|
|
LightInput light; |
|
|
|
INITIALIZE_MAIN_LIGHT(light); |
|
|
|
half lightAtten = ComputeLightAttenuation(light, normal, i.posWS.xyz, lightDirection); |
|
|
|
LightInput light; |
|
|
|
INITIALIZE_MAIN_LIGHT(light); |
|
|
|
half lightAtten = ComputeLightAttenuation(light, normal, posWS.xyz, lightDirection); |
|
|
|
lightAtten *= ComputeShadowAttenuation(vertexNormal, i.posWS, _ShadowLightDirection.xyz); |
|
|
|
lightAtten *= ComputeShadowAttenuation(vertexNormal, posWS, _ShadowLightDirection.xyz); |
|
|
|
half NdotL = saturate(dot(normal, lightDirection)); |
|
|
|
half3 radiance = light.color * (lightAtten * NdotL); |
|
|
|
color += LightweightBDRF(diffColor, specColor, oneMinusReflectivity, perceptualRoughness, normal, lightDirection, i.viewDir.xyz) * radiance; |
|
|
|
half NdotL = saturate(dot(norm, lightDirection)); |
|
|
|
half3 radiance = light.color * (lightAtten * NdotL); |
|
|
|
color += LightweightBDRF(diffColor, specColor, oneMinusReflectivity, perceptualRoughness, norm, lightDirection, viewDir.xyz) * radiance; |
|
|
|
half shadowAttenuation = ComputeShadowAttenuation(vertexNormal, i.posWS, _ShadowLightDirection.xyz); |
|
|
|
half shadowAttenuation = ComputeShadowAttenuation(vertexNormal, posWS, _ShadowLightDirection.xyz); |
|
|
|
int pixelLightCount = min(globalLightCount.x, unity_LightIndicesOffsetAndCount.y); |
|
|
|
for (int lightIter = 0; lightIter < pixelLightCount; ++lightIter) |
|
|
|
{ |
|
|
|
LightInput light; |
|
|
|
int lightIndex = unity_4LightIndices0[lightIter]; |
|
|
|
INITIALIZE_LIGHT(light, lightIndex); |
|
|
|
half lightAtten = ComputeLightAttenuation(light, normal, i.posWS.xyz, lightDirection); |
|
|
|
int pixelLightCount = min(globalLightCount.x, unity_LightIndicesOffsetAndCount.y); |
|
|
|
for (int lightIter = 0; lightIter < pixelLightCount; ++lightIter) |
|
|
|
{ |
|
|
|
LightInput light; |
|
|
|
int lightIndex = unity_4LightIndices0[lightIter]; |
|
|
|
INITIALIZE_LIGHT(light, lightIndex); |
|
|
|
half lightAtten = ComputeLightAttenuation(light, norm, posWS.xyz, lightDirection); |
|
|
|
lightAtten *= max(shadowAttenuation, half(lightIndex != _ShadowData.x)); |
|
|
|
lightAtten *= max(shadowAttenuation, half(lightIndex != _ShadowData.x)); |
|
|
|
half NdotL = saturate(dot(normal, lightDirection)); |
|
|
|
half3 radiance = light.color * (lightAtten * NdotL); |
|
|
|
half NdotL = saturate(dot(norm, lightDirection)); |
|
|
|
half3 radiance = light.color * (lightAtten * NdotL); |
|
|
|
color += LightweightBDRF(diffColor, specColor, oneMinusReflectivity, perceptualRoughness, normal, lightDirection, i.viewDir.xyz) * radiance; |
|
|
|
} |
|
|
|
color += LightweightBDRF(diffColor, specColor, oneMinusReflectivity, perceptualRoughness, norm, lightDirection, viewDir.xyz) * radiance; |
|
|
|
} |
|
|
|
color += o.Emission; |
|
|
|
UNITY_APPLY_FOG(i.fogCoord, color); |
|
|
|
return OutputColor(color, o.Alpha); |
|
|
|
color += emission; |
|
|
|
UNITY_APPLY_FOG(fogCoord, color); |
|
|
|
return OutputColor(color, alpha); |
|
|
|
} |
|
|
|
|
|
|
|
half4 LightweightFragmentPBR(VertOutput i) : SV_Target |
|
|
|
{ |
|
|
|
SurfacePBR o = InitializeSurfacePBR(); |
|
|
|
DefineSurface(i, o); |
|
|
|
return FragmentLightingPBR(i.meshUV0, i.posWS, i.normal, i.tangent, i.binormal, i.viewDir, i.fogCoord, |
|
|
|
o.Albedo, o.Metallic, o.Specular, o.Smoothness, o.Normal, o.Occlusion, o.Emission, o.Alpha); |
|
|
|
} |
|
|
|
|
|
|
|
#endif |