#ifndef PBR_FORWARD
#define PBR_FORWARD
inline void CustInitializeBRDFData(half3 albedo, half metallic, half3 specular, half smoothness, half alpha, out BRDFData outBRDFData)
{
#ifdef _SPECULAR_SETUP
    half reflectivity = ReflectivitySpecular(specular);
    half oneMinusReflectivity = 1.0 - reflectivity;

    outBRDFData.diffuse = albedo * (half3(1.0h, 1.0h, 1.0h) - specular);
    outBRDFData.specular = specular;
#else

    half oneMinusReflectivity = OneMinusReflectivityMetallic(metallic);
    half reflectivity = 1.0 - oneMinusReflectivity;

    outBRDFData.diffuse = albedo * (_Metal_ON?oneMinusReflectivity:1);
    outBRDFData.specular = lerp(kDieletricSpec.rgb, albedo, metallic);
#endif

    outBRDFData.grazingTerm = saturate(smoothness + reflectivity);
    outBRDFData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness);
    outBRDFData.roughness = max(PerceptualRoughnessToRoughness(outBRDFData.perceptualRoughness), HALF_MIN);
    outBRDFData.roughness2 = outBRDFData.roughness * outBRDFData.roughness;

    outBRDFData.normalizationTerm = outBRDFData.roughness * 4.0h + 2.0h;
    outBRDFData.roughness2MinusOne = outBRDFData.roughness2 - 1.0h;

#ifdef _ALPHAPREMULTIPLY_ON
    outBRDFData.diffuse *= alpha;
    alpha = alpha * oneMinusReflectivity + reflectivity;
#endif
}
half4 CustDirectBDRF(BRDFData brdfData, half3 normalWS, half3 lightDirectionWS, half3 viewDirectionWS,half SpecStrength)
{
    float3 halfDir = SafeNormalize(float3(lightDirectionWS) + float3(viewDirectionWS));

    float NoH = saturate(dot(normalWS, halfDir));
    half LoH = saturate(dot(lightDirectionWS, halfDir));
    float d = NoH * NoH * brdfData.roughness2MinusOne + 1.00001f;

    half LoH2 = LoH * LoH;
    half specularTerm = brdfData.roughness2 / ((d * d) * max(0.1h, LoH2) * brdfData.normalizationTerm);
#if defined (SHADER_API_MOBILE) || defined (SHADER_API_SWITCH)
    specularTerm = specularTerm - HALF_MIN;
    specularTerm = clamp(specularTerm, 0.0, 100.0);
#endif
	half3 brdf = specularTerm * brdfData.specular * SpecStrength;
    half3 color = brdf + brdfData.diffuse;
    return half4(color,dot(brdf, half3(0.3, 0.59, 0.11)));
}
half4 CustLightingPhysicallyBased(BRDFData brdfData, Light light,half3 LightColor, half lightAttenuation, half3 normalWS, half3 viewDirectionWS,half SpecStrength)
{
	half NdotL = saturate(dot(normalWS, light.direction));
	half4 diffuse = CustDirectBDRF(brdfData, normalWS, light.direction, viewDirectionWS, SpecStrength);

    half artist_lerp = light.distanceAttenuation;
#if defined(_MIXED_LIGHTING_SUBTRACTIVE)
    artist_lerp = lerp(light.distanceAttenuation,1,diffuse.a);
#endif
    LightColor = lerp(LightColor,1,saturate(_envir_brightness.w));
	half3 radiance = LightColor * (artist_lerp*lightAttenuation) * _diffuse_intensity;
	return half4(diffuse.rgb* radiance,diffuse.a);
}
half3 CustGlobalIllumination(BRDFData brdfData, half3 bakedGI, half occlusion, half3 normalWS, half3 viewDirectionWS, half RefIntensity)
{
    half3 reflectVector = reflect(-viewDirectionWS, normalWS);
    half fresnelTerm = Pow4(1.0 - saturate(dot(normalWS, viewDirectionWS)));

    half3 indirectDiffuse = bakedGI * occlusion;
    half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, brdfData.perceptualRoughness, occlusion*RefIntensity);

    return EnvironmentBRDF(brdfData, indirectDiffuse, indirectSpecular, fresnelTerm);
 }
#endif