浏览代码

Refactor on LiweightPassLit + BRDF

/RenderPassXR_Sandbox
Felipe Lira 7 年前
当前提交
5ce0e5d7
共有 5 个文件被更改,包括 148 次插入114 次删除
  1. 40
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightBRDF.cginc
  2. 30
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCore.cginc
  3. 72
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.cginc
  4. 5
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc
  5. 115
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.cginc

40
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightBRDF.cginc


#define PI 3.14159265359f
half MetallicSetup_Reflectivity()
{
return 1.0h - OneMinusReflectivityFromMetallic(_Metallic);
}
half3 LightweightBRDFDirect(half3 diffColor, half3 specColor, half smoothness, half RdotL)
{
#ifndef _SPECULARHIGHLIGHTS_OFF
half RdotLPow4 = Pow4(RdotL);
half LUT_RANGE = 16.0; // must match range in NHxRoughness() function in GeneratedTextures.cpp
// Lookup texture to save instructions
half perceptualRoughness = 1.0 - smoothness;
half specular = tex2D(unity_NHxRoughness, half2(RdotLPow4, perceptualRoughness)).UNITY_ATTEN_CHANNEL * LUT_RANGE;
return diffColor + specular * specColor;
#else
return diffColor;
#endif
}
// Based on Minimalist CookTorrance BRDF
// Implementation is slightly different from original derivation: http://www.thetenthplanet.de/archives/255
//

half3 LightweightBDRF(half3 diffColor, half3 specColor, half oneMinusReflectivity, half perceptualRoughness, half3 normal, half3 lightDirection, half3 viewDir)
half3 LightweightBDRF(BRDFData brdfData, half roughness2, half3 normal, half3 lightDirection, half3 viewDir)
{
#ifndef _SPECULARHIGHLIGHTS_OFF
half3 halfDir = Unity_SafeNormalize(lightDirection + viewDir);

// Specular term
half roughness = perceptualRoughness * perceptualRoughness;
half a2 = roughness * roughness;
half d = NoH * NoH * (a2 - 1.h) + 1.00001h;
half d = NoH * NoH * (roughness2 - 1.h) + 1.00001h;
half specularTerm = a2 / ((d * d) * max(0.1h, LoH2) * (roughness + 0.5h) * 4);
half specularTerm = roughness2 / ((d * d) * max(0.1h, LoH2) * (brdfData.roughness + 0.5h) * 4);
// on mobiles (where half actually means something) denominator have risk of overflow
// clamp below was added specifically to "fix" that, but dx compiler (we convert bytecode to metal/gles)

specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles
#endif
return diffColor + specularTerm * specColor;
half3 color = specularTerm * brdfData.specular + brdfData.diffuse;
return color;
half3 LightweightBRDFIndirect(half3 diffColor, half3 specColor, UnityIndirect indirect, float roughness, half grazingTerm, half fresnelTerm)
half3 LightweightBRDFIndirect(BRDFData brdfData, UnityIndirect indirect, half roughness2, half fresnelTerm)
half3 c = indirect.diffuse * diffColor;
float surfaceReduction = 1.0 / (roughness * roughness + 1.0);
c += surfaceReduction * indirect.specular * lerp(specColor, grazingTerm, fresnelTerm);
half3 c = indirect.diffuse * brdfData.diffuse;
float surfaceReduction = 1.0 / (roughness2 + 1.0);
c += surfaceReduction * indirect.specular * lerp(brdfData.specular, brdfData.grazingTerm, fresnelTerm);
return c;
}

30
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCore.cginc


#define LIGHTWEIGHT_SPECULAR_HIGHLIGHTS
#endif
#define _DieletricSpec half4(0.04, 0.04, 0.04, 1.0 - 0.04) // standard dielectric reflectivity coef at incident angle (= 4%)
half SpecularReflectivity(half3 specular)
{
#if (SHADER_TARGET < 30)

#endif
}
half3 MetallicSetup(float2 uv, half3 albedo, half albedoAlpha, out half3 specular, out half smoothness, out half oneMinusReflectivity)
{
half2 metallicGloss = MetallicSpecGloss(uv, albedoAlpha).ra;
half metallic = metallicGloss.r;
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
half oneMinusDielectricSpec = _DieletricSpec.a;
oneMinusReflectivity = oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
specular = lerp(_DieletricSpec.rgb, albedo, metallic);
return albedo * oneMinusReflectivity;
}
half3 SpecularSetup(float2 uv, half3 albedo, half albedoAlpha, out half3 specular, out half smoothness, out half oneMinusReflectivity)
{
half4 specGloss = MetallicSpecGloss(uv, albedoAlpha);
specular = specGloss.rgb;
smoothness = specGloss.a;
oneMinusReflectivity = 1.0h - SpecularReflectivity(specular);
return albedo * (half3(1, 1, 1) - specular);
}
half4 OutputColor(half3 color, half alpha)
{
#if defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)

#endif
}
#endif

72
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightInput.cginc


UNITY_VERTEX_OUTPUT_STEREO
};
inline void NormalMap(LightweightVertexOutput i, out half3 normal)
struct SurfaceData
#if _NORMALMAP
half3 normalmap = UnpackNormal(tex2D(_BumpMap, i.uv01.xy));
half3 albedo;
half alpha;
half4 metallicSpecGloss;
half3 normalWorld;
half ao;
half3 emission;
};
struct BRDFData
{
half3 diffuse;
half3 specular;
half perceptualRoughness;
half roughness;
half oneMinusReflectivity;
half grazingTerm;
};
inline half Alpha(half albedoAlpha)
{
#if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
half alpha = _Color.a;
#else
half alpha = albedoAlpha * _Color.a;
#endif
#if defined(_ALPHATEST_ON)
clip(alpha - _Cutoff);
#endif
return alpha;
}
inline half3 Normal(LightweightVertexOutput i)
{
#if _NORMALMAP
half3 normalTangent = UnpackNormal(tex2D(_BumpMap, i.uv01.xy));
normal = normalize(half3(dot(normalmap, i.tangentToWorld0), dot(normalmap, i.tangentToWorld1), dot(normalmap, i.tangentToWorld2)));
half3 normalWorld = normalize(half3(dot(normalTangent, i.tangentToWorld0), dot(normalTangent, i.tangentToWorld1), dot(normalTangent, i.tangentToWorld2)));
normal = normalize(i.normal);
half3 normalWorld = normalize(i.normal);
return normalWorld;
}
inline void SpecularGloss(half2 uv, half alpha, out half4 specularGloss)

half4 specGloss;
#ifdef _METALLICSPECGLOSSMAP
specGloss = SAMPLE_METALLICSPECULAR(uv);
specGloss = specGloss = SAMPLE_METALLICSPECULAR(uv);
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
specGloss.a = albedoAlpha * _GlossMapScale;
#else

#else // _METALLICSPECGLOSSMAP
#if _METALLIC_SETUP
specGloss.r = _Metallic;
specGloss.rgb = _Metallic.rrr;
#else
specGloss.rgb = _SpecColor.rgb;
#endif

#endif
return specGloss;
}
half OcclusionLW(float2 uv)
{
#if (SHADER_TARGET < 30)
// SM20: instruction count limitation
// SM20: simpler occlusion
return tex2D(_OcclusionMap, uv).g;
#else
half occ = tex2D(_OcclusionMap, uv).g;
return LerpOneTo(occ, _OcclusionStrength);
#endif
}
half3 EmissionLW(float2 uv)
{
#ifndef _EMISSION
return 0;
#else
return LIGHTWEIGHT_GAMMA_TO_LINEAR(tex2D(_EmissionMap, uv).rgb) * _EmissionColor.rgb;
#endif
}
#endif

5
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc


#ifndef LIGHTWEIGHT_LIGHTING_INCLUDED
#define LIGHTWEIGHT_LIGHTING_INCLUDED
UnityIndirect LightweightGI(float2 lightmapUV, half3 ambientColor, half3 normalWorld, half3 reflectVec, half occlusion, half roughness)
UnityIndirect LightweightGI(float2 lightmapUV, half3 ambientColor, half3 normalWorld, half3 reflectVec, half occlusion, half perceptualRoughness)
{
UnityIndirect o = (UnityIndirect)0;
#ifdef LIGHTMAP_ON

o.diffuse = ambientColor * occlusion;
#ifndef _GLOSSYREFLECTIONS_OFF
// perceptualRoughness
g.roughness = roughness;
g.roughness = perceptualRoughness;
g.reflUVW = reflectVec;
o.specular = Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, g) * occlusion;
#else

115
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.cginc


#include "LightweightCore.cginc"
#define kDieletricSpec half4(0.04, 0.04, 0.04, 1.0 - 0.04) // standard dielectric reflectivity coef at incident angle (= 4%)
inline void InitializeSurfaceData(LightweightVertexOutput i, out SurfaceData outSurfaceData)
{
float2 uv = i.uv01.xy;
half4 albedoAlpha = tex2D(_MainTex, uv);
outSurfaceData.albedo = LIGHTWEIGHT_GAMMA_TO_LINEAR(albedoAlpha.rgb) * _Color.rgb;
outSurfaceData.alpha = Alpha(albedoAlpha.a);
outSurfaceData.metallicSpecGloss = MetallicSpecGloss(uv, albedoAlpha);
outSurfaceData.normalWorld = Normal(i);
outSurfaceData.ao = OcclusionLW(uv);
outSurfaceData.emission = EmissionLW(uv);
}
inline void InitializeBRDFData(SurfaceData surfaceData, out BRDFData outBRDFData)
{
// BRDF SETUP
#ifdef _METALLIC_SETUP
half2 metallicGloss = surfaceData.metallicSpecGloss.ra;
half metallic = metallicGloss.r;
half smoothness = metallicGloss.g;
// We'll need oneMinusReflectivity, so
// 1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) = lerp(1-dielectricSpec, 0, metallic)
// store (1-dielectricSpec) in kDieletricSpec.a, then
// 1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) =
// = alpha - metallic * alpha
half oneMinusDielectricSpec = kDieletricSpec.a;
half oneMinusReflectivity = oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
half reflectivity = 1.0 - oneMinusReflectivity;
outBRDFData.diffuse = surfaceData.albedo * oneMinusReflectivity;
outBRDFData.specular = lerp(kDieletricSpec.rgb, surfaceData.albedo, metallic);
outBRDFData.oneMinusReflectivity = oneMinusReflectivity;
#else
half3 specular = surfaceData.metallicSpecGloss.rgb;
half smoothness = surfaceData.metallicSpecGloss.a;
half reflectivity = SpecularReflectivity(specular);
outBRDFData.diffuse = surfaceData.albedo * (half3(1.0h, 1.0h, 1.0h) - specular);
outBRDFData.specular = specular;
outBRDFData.oneMinusReflectivity = 1.0h - reflectivity;
#endif
outBRDFData.grazingTerm = saturate(smoothness + reflectivity);
outBRDFData.perceptualRoughness = 1.0h - smoothness;
outBRDFData.roughness = outBRDFData.perceptualRoughness * outBRDFData.perceptualRoughness;
#ifdef _ALPHAPREMULTIPLY_ON
half alpha = surfaceData.alpha;
outBRDFData.diffuse *= alpha;
surfaceData.alpha = reflectivity + alpha * oneMinusReflectivity;
#endif
}
LightweightVertexOutput LitPassVertex(LightweightVertexInput v)
{
LightweightVertexOutput o = (LightweightVertexOutput)0;

half4 LitPassFragment(LightweightVertexOutput i) : SV_Target
{
float2 uv = i.uv01.xy;
float2 lightmapUV = i.uv01.zw;
SurfaceData surfaceData;
InitializeSurfaceData(i, surfaceData);
half4 albedoTex = tex2D(_MainTex, i.uv01.xy);
half3 albedo = LIGHTWEIGHT_GAMMA_TO_LINEAR(albedoTex.rgb) * _Color.rgb;
BRDFData brdfData;
InitializeBRDFData(surfaceData, brdfData);
#if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
half alpha = _Color.a;
#else
half alpha = albedoTex.a * _Color.a;
#endif
#if defined(_ALPHATEST_ON)
clip(alpha - _Cutoff);
#endif
half3 specColor;
half smoothness;
half oneMinusReflectivity;
#ifdef _METALLIC_SETUP
half3 diffColor = MetallicSetup(uv, albedo, alpha, specColor, smoothness, oneMinusReflectivity);
#else
half3 diffColor = SpecularSetup(uv, albedo, alpha, specColor, smoothness, oneMinusReflectivity);
#endif
diffColor = PreMultiplyAlpha(diffColor, alpha, oneMinusReflectivity, /*out*/ alpha);
// Roughness is (1.0 - smoothness)�
half perceptualRoughness = 1.0h - smoothness;
half3 normal;
NormalMap(i, normal);
// TODO: shader keyword for occlusion
// TODO: Reflection Probe blend support.
float2 lightmapUV = i.uv01.zw;
half3 normal = surfaceData.normalWorld;
half occlusion = Occlusion(uv);
UnityIndirect indirectLight = LightweightGI(lightmapUV, i.fogCoord.yzw, normal, reflectVec, occlusion, perceptualRoughness);
half roughness2 = brdfData.roughness * brdfData.roughness;
UnityIndirect indirectLight = LightweightGI(lightmapUV, i.fogCoord.yzw, normal, reflectVec, surfaceData.ao, brdfData.perceptualRoughness);
// grazingTerm = F90
half grazingTerm = saturate(smoothness + (1 - oneMinusReflectivity));
half3 color = LightweightBRDFIndirect(diffColor, specColor, indirectLight, perceptualRoughness * perceptualRoughness, grazingTerm, fresnelTerm);
half3 color = LightweightBRDFIndirect(brdfData, indirectLight, roughness2, fresnelTerm);
half3 lightDirection;
#ifndef _MULTIPLE_LIGHTS

half NdotL = saturate(dot(normal, lightDirection));
half3 radiance = light.color * (lightAtten * NdotL);
color += LightweightBDRF(diffColor, specColor, oneMinusReflectivity, perceptualRoughness, normal, lightDirection, i.viewDir.xyz) * radiance;
color += LightweightBDRF(brdfData, roughness2, normal, lightDirection, i.viewDir.xyz) * radiance;
#else
#ifdef _SHADOWS

half NdotL = saturate(dot(normal, lightDirection));
half3 radiance = light.color * (lightAtten * NdotL);
color += LightweightBDRF(diffColor, specColor, oneMinusReflectivity, perceptualRoughness, normal, lightDirection, i.viewDir.xyz) * radiance;
color += LightweightBDRF(brdfData, roughness2, normal, lightDirection, i.viewDir.xyz) * radiance;
color += Emission(uv);
color += surfaceData.emission;
return OutputColor(color, alpha);
return OutputColor(color, surfaceData.alpha);
}
half4 LitPassFragmentSimple(LightweightVertexOutput i) : SV_Target

clip(alpha - _Cutoff);
#endif
half3 normal;
NormalMap(i, normal);
half3 normal = Normal(i);
half4 specularGloss;
SpecularGloss(i.uv01.xy, alpha, specularGloss);

正在加载...
取消
保存