<fragment uiName="usdPreviewSurfaceLighting" name="usdPreviewSurfaceLighting" type="plumbing" class="ShadeFragment" version="1.0" feature_level="0">
    <!-- WARNING: Do not edit this file. It was automatically generated by pxrUsdPreviewSurfaceGenFragments. -->
    <description>
        Computes the diffuse and specular lighting contributions for a light.
    </description>
    <properties>
        <!-- UsdPreviewSurface Parameters -->
        <float3 name="diffuseColor"/>
        <bool name="useSpecularWorkflow"/>
        <float name="ior"/>
        <float name="metallic"/>
        <float name="specularAmount"/>
        <float3 name="specularColor"/>
        <float name="specularRoughness"/>
        <float name="clearcoatAmount"/>
        <float3 name="clearcoatColor"/>
        <float name="clearcoatRoughness"/>
        <float name="occlusion"/>

        <!-- Dot products for lighting computed by Maya's mayaShaderGeom fragment. -->
        <float name="NdotL"/>
        <float name="NdotV"/>
        <float name="NdotH"/>
        <float name="VdotH"/>

        <!-- Irradiance values from Maya for the light being computed. The
             irradiance accounts for shadowing and attenuation of the light. -->
        <float3 name="diffuseIrradiance"/>
        <float3 name="specularIrradiance"/>
    </properties>
    <values>
        <!-- UsdPreviewSurface Parameter Default Values -->
        <float3 name="diffuseColor" value="0.18,0.18,0.18"/>
        <bool name="useSpecularWorkflow" value="false"/>
        <float name="ior" value="1.5"/>
        <float name="metallic" value="0.0"/>
        <float name="specularAmount" value="1.0"/>
        <float3 name="specularColor" value="0.0,0.0,0.0"/>
        <float name="specularRoughness" value="0.5"/>
        <float name="clearcoatAmount" value="0.0"/>
        <float3 name="clearcoatColor" value="1.0,1.0,1.0"/>
        <float name="clearcoatRoughness" value="0.01"/>
        <float name="occlusion" value="1.0"/>

        <!-- Default values for Maya-provided parameters. -->
        <float name="NdotL" value="0.0"/>
        <float name="NdotV" value="0.0"/>
        <float name="NdotH" value="0.0"/>
        <float name="VdotH" value="0.0"/>

        <float3 name="diffuseIrradiance" value="0.0,0.0,0.0"/>
        <float3 name="specularIrradiance" value="0.0,0.0,0.0"/>
    </values>
    <outputs>
        <struct name="usdPreviewSurfaceLighting" struct_name="LightingContributions"/>
    </outputs>
    <implementation>
        <implementation render="OGSRenderer" language="Cg" lang_version="2.1">
            <function_name val="usdPreviewSurfaceLighting"/>
            <source>
                <![CDATA[

// Check whether we're in a GLSL context. If so, we don't expect "floatN"
// types to exist, so we use "vecN" types instead.
#if defined(__VERSION__) && (__VERSION__ >= 110)
#define float3 vec3
#endif

// line 110 of "../../../../pxr/usdImaging/lib/usdShaders/shaders/previewSurface.glslfx"

#define PI 3.1415
#define EPSILON 0.001


float
SchlickFresnel(float EdotH)
{
    return pow(max(0.0, 1.0 - EdotH), 5.0);
}

float
NormalDistribution(float specularRoughness, float NdotH)
{
    float alpha = specularRoughness * specularRoughness;
    float alpha2 = alpha * alpha;
    float NdotH2 = NdotH * NdotH;
    float DDenom = (NdotH2 * (alpha2 - 1.0)) + 1.0;
    DDenom *= DDenom;
    DDenom *= PI;
    float D = (alpha2 + EPSILON) / DDenom;
    return D;
}

float
Geometric(
        float specularRoughness,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH)
{
    float alpha = specularRoughness * specularRoughness;
    float k = alpha * 0.5;
    float G = NdotE / (NdotE * (1.0 - k) + k);
    G *= NdotL / (NdotL * (1.0 - k) + k);
    return G;
}

float3
evaluateDirectDiffuse()
{
    return float3(1.0 / PI);
}

float3
evaluateDirectSpecular(
        float3 specularColorF0,
        float3 specularColorF90,
        float specularRoughness,
        float fresnel,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH)
{
    float3 F = mix(specularColorF0, specularColorF90, fresnel);
    float D = NormalDistribution(specularRoughness, NdotH);
    float G = Geometric(specularRoughness, NdotL, NdotE, NdotH, EdotH);
    float3 RNum = F * G * D;
    float RDenom = 4.0f * NdotL * NdotE + EPSILON;
    return RNum / RDenom;
}

LightingContributions
usdPreviewSurfaceLighting(
        float3 diffuseColor,
        bool useSpecularWorkflow,
        float ior,
        float metallic,
        float specularAmount,
        float3 specularColor,
        float specularRoughness,
        float clearcoatAmount,
        float3 clearcoatColor,
        float clearcoatRoughness,
        float occlusion,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH,
        float3 lightDiffuseIrradiance,
        float3 lightSpecularIrradiance)
{
    specularRoughness = max(0.001, specularRoughness);
    clearcoatRoughness = max(0.001, clearcoatRoughness);

    float fresnel = SchlickFresnel(EdotH);

    // Evaluate diffuse
    float3 d = diffuseColor * evaluateDirectDiffuse();

    // Evaluate specular first lobe
    float3 s1 = float3(0.0);
    if (specularAmount > 0.0) {
        float3 F0 = specularColor;
        float3 F90 = float3(1.0);

        if (!useSpecularWorkflow) {
            float R = (1.0 - ior) / (1.0 + ior);
            float3 specColor = mix(float3(1.0), diffuseColor, metallic);
            F0  = R * R * specColor;
            F90 = specColor;

            // For metallic workflows, pure metals have no diffuse
            d *= 1.0 - metallic;
        }

        s1 = specularAmount * evaluateDirectSpecular(
             F0,                          // Specular color 0
             F90,                         // Specular color 90
             specularRoughness,           // Roughness
             fresnel,                     // Fresnel
             NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights

        // Adjust the diffuse so glazing angles have less diffuse
        d *= (1.0 - mix(F0, F90, fresnel));
    }

    // Evaluate clearcoat
    float3 s2 = float3(0.0);
    if (clearcoatAmount > 0.0) {
        s2 = clearcoatAmount * evaluateDirectSpecular(
             clearcoatColor,              // Clearcoat color 0
             clearcoatColor,              // Clearcoat color 90
             clearcoatRoughness,          // Roughness
             fresnel,                     // Fresnel
             NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights
    }

    LightingContributions lightingContrib;

    lightingContrib.diffuse =
        occlusion * NdotL * d * lightDiffuseIrradiance;

    lightingContrib.specular =
        occlusion * NdotL * (s1 + s2) * lightSpecularIrradiance;

    return lightingContrib;
}


]]>
            </source>
        </implementation>
        <implementation render="OGSRenderer" language="GLSL" lang_version="3.0">
            <function_name val="usdPreviewSurfaceLighting"/>
            <source>
                <![CDATA[

// Check whether we're in a GLSL context. If so, we don't expect "floatN"
// types to exist, so we use "vecN" types instead.
#if defined(__VERSION__) && (__VERSION__ >= 110)
#define float3 vec3
#endif

// line 110 of "../../../../pxr/usdImaging/lib/usdShaders/shaders/previewSurface.glslfx"

#define PI 3.1415
#define EPSILON 0.001


float
SchlickFresnel(float EdotH)
{
    return pow(max(0.0, 1.0 - EdotH), 5.0);
}

float
NormalDistribution(float specularRoughness, float NdotH)
{
    float alpha = specularRoughness * specularRoughness;
    float alpha2 = alpha * alpha;
    float NdotH2 = NdotH * NdotH;
    float DDenom = (NdotH2 * (alpha2 - 1.0)) + 1.0;
    DDenom *= DDenom;
    DDenom *= PI;
    float D = (alpha2 + EPSILON) / DDenom;
    return D;
}

float
Geometric(
        float specularRoughness,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH)
{
    float alpha = specularRoughness * specularRoughness;
    float k = alpha * 0.5;
    float G = NdotE / (NdotE * (1.0 - k) + k);
    G *= NdotL / (NdotL * (1.0 - k) + k);
    return G;
}

float3
evaluateDirectDiffuse()
{
    return float3(1.0 / PI);
}

float3
evaluateDirectSpecular(
        float3 specularColorF0,
        float3 specularColorF90,
        float specularRoughness,
        float fresnel,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH)
{
    float3 F = mix(specularColorF0, specularColorF90, fresnel);
    float D = NormalDistribution(specularRoughness, NdotH);
    float G = Geometric(specularRoughness, NdotL, NdotE, NdotH, EdotH);
    float3 RNum = F * G * D;
    float RDenom = 4.0f * NdotL * NdotE + EPSILON;
    return RNum / RDenom;
}

LightingContributions
usdPreviewSurfaceLighting(
        float3 diffuseColor,
        bool useSpecularWorkflow,
        float ior,
        float metallic,
        float specularAmount,
        float3 specularColor,
        float specularRoughness,
        float clearcoatAmount,
        float3 clearcoatColor,
        float clearcoatRoughness,
        float occlusion,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH,
        float3 lightDiffuseIrradiance,
        float3 lightSpecularIrradiance)
{
    specularRoughness = max(0.001, specularRoughness);
    clearcoatRoughness = max(0.001, clearcoatRoughness);

    float fresnel = SchlickFresnel(EdotH);

    // Evaluate diffuse
    float3 d = diffuseColor * evaluateDirectDiffuse();

    // Evaluate specular first lobe
    float3 s1 = float3(0.0);
    if (specularAmount > 0.0) {
        float3 F0 = specularColor;
        float3 F90 = float3(1.0);

        if (!useSpecularWorkflow) {
            float R = (1.0 - ior) / (1.0 + ior);
            float3 specColor = mix(float3(1.0), diffuseColor, metallic);
            F0  = R * R * specColor;
            F90 = specColor;

            // For metallic workflows, pure metals have no diffuse
            d *= 1.0 - metallic;
        }

        s1 = specularAmount * evaluateDirectSpecular(
             F0,                          // Specular color 0
             F90,                         // Specular color 90
             specularRoughness,           // Roughness
             fresnel,                     // Fresnel
             NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights

        // Adjust the diffuse so glazing angles have less diffuse
        d *= (1.0 - mix(F0, F90, fresnel));
    }

    // Evaluate clearcoat
    float3 s2 = float3(0.0);
    if (clearcoatAmount > 0.0) {
        s2 = clearcoatAmount * evaluateDirectSpecular(
             clearcoatColor,              // Clearcoat color 0
             clearcoatColor,              // Clearcoat color 90
             clearcoatRoughness,          // Roughness
             fresnel,                     // Fresnel
             NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights
    }

    LightingContributions lightingContrib;

    lightingContrib.diffuse =
        occlusion * NdotL * d * lightDiffuseIrradiance;

    lightingContrib.specular =
        occlusion * NdotL * (s1 + s2) * lightSpecularIrradiance;

    return lightingContrib;
}


]]>
            </source>
        </implementation>
        <implementation render="OGSRenderer" language="HLSL" lang_version="10.0">
            <function_name val="usdPreviewSurfaceLighting"/>
            <source>
                <![CDATA[

// Check whether we're in a GLSL context. If so, we don't expect "floatN"
// types to exist, so we use "vecN" types instead.
#if defined(__VERSION__) && (__VERSION__ >= 110)
#define float3 vec3
#endif

// line 110 of "../../../../pxr/usdImaging/lib/usdShaders/shaders/previewSurface.glslfx"

#define PI 3.1415
#define EPSILON 0.001


float
SchlickFresnel(float EdotH)
{
    return pow(max(0.0, 1.0 - EdotH), 5.0);
}

float
NormalDistribution(float specularRoughness, float NdotH)
{
    float alpha = specularRoughness * specularRoughness;
    float alpha2 = alpha * alpha;
    float NdotH2 = NdotH * NdotH;
    float DDenom = (NdotH2 * (alpha2 - 1.0)) + 1.0;
    DDenom *= DDenom;
    DDenom *= PI;
    float D = (alpha2 + EPSILON) / DDenom;
    return D;
}

float
Geometric(
        float specularRoughness,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH)
{
    float alpha = specularRoughness * specularRoughness;
    float k = alpha * 0.5;
    float G = NdotE / (NdotE * (1.0 - k) + k);
    G *= NdotL / (NdotL * (1.0 - k) + k);
    return G;
}

float3
evaluateDirectDiffuse()
{
    return float3(1.0 / PI);
}

float3
evaluateDirectSpecular(
        float3 specularColorF0,
        float3 specularColorF90,
        float specularRoughness,
        float fresnel,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH)
{
    float3 F = mix(specularColorF0, specularColorF90, fresnel);
    float D = NormalDistribution(specularRoughness, NdotH);
    float G = Geometric(specularRoughness, NdotL, NdotE, NdotH, EdotH);
    float3 RNum = F * G * D;
    float RDenom = 4.0f * NdotL * NdotE + EPSILON;
    return RNum / RDenom;
}

LightingContributions
usdPreviewSurfaceLighting(
        float3 diffuseColor,
        bool useSpecularWorkflow,
        float ior,
        float metallic,
        float specularAmount,
        float3 specularColor,
        float specularRoughness,
        float clearcoatAmount,
        float3 clearcoatColor,
        float clearcoatRoughness,
        float occlusion,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH,
        float3 lightDiffuseIrradiance,
        float3 lightSpecularIrradiance)
{
    specularRoughness = max(0.001, specularRoughness);
    clearcoatRoughness = max(0.001, clearcoatRoughness);

    float fresnel = SchlickFresnel(EdotH);

    // Evaluate diffuse
    float3 d = diffuseColor * evaluateDirectDiffuse();

    // Evaluate specular first lobe
    float3 s1 = float3(0.0);
    if (specularAmount > 0.0) {
        float3 F0 = specularColor;
        float3 F90 = float3(1.0);

        if (!useSpecularWorkflow) {
            float R = (1.0 - ior) / (1.0 + ior);
            float3 specColor = mix(float3(1.0), diffuseColor, metallic);
            F0  = R * R * specColor;
            F90 = specColor;

            // For metallic workflows, pure metals have no diffuse
            d *= 1.0 - metallic;
        }

        s1 = specularAmount * evaluateDirectSpecular(
             F0,                          // Specular color 0
             F90,                         // Specular color 90
             specularRoughness,           // Roughness
             fresnel,                     // Fresnel
             NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights

        // Adjust the diffuse so glazing angles have less diffuse
        d *= (1.0 - mix(F0, F90, fresnel));
    }

    // Evaluate clearcoat
    float3 s2 = float3(0.0);
    if (clearcoatAmount > 0.0) {
        s2 = clearcoatAmount * evaluateDirectSpecular(
             clearcoatColor,              // Clearcoat color 0
             clearcoatColor,              // Clearcoat color 90
             clearcoatRoughness,          // Roughness
             fresnel,                     // Fresnel
             NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights
    }

    LightingContributions lightingContrib;

    lightingContrib.diffuse =
        occlusion * NdotL * d * lightDiffuseIrradiance;

    lightingContrib.specular =
        occlusion * NdotL * (s1 + s2) * lightSpecularIrradiance;

    return lightingContrib;
}


]]>
            </source>
        </implementation>
        <implementation render="OGSRenderer" language="HLSL" lang_version="11.0">
            <function_name val="usdPreviewSurfaceLighting"/>
            <source>
                <![CDATA[

// Check whether we're in a GLSL context. If so, we don't expect "floatN"
// types to exist, so we use "vecN" types instead.
#if defined(__VERSION__) && (__VERSION__ >= 110)
#define float3 vec3
#endif

// line 110 of "../../../../pxr/usdImaging/lib/usdShaders/shaders/previewSurface.glslfx"

#define PI 3.1415
#define EPSILON 0.001


float
SchlickFresnel(float EdotH)
{
    return pow(max(0.0, 1.0 - EdotH), 5.0);
}

float
NormalDistribution(float specularRoughness, float NdotH)
{
    float alpha = specularRoughness * specularRoughness;
    float alpha2 = alpha * alpha;
    float NdotH2 = NdotH * NdotH;
    float DDenom = (NdotH2 * (alpha2 - 1.0)) + 1.0;
    DDenom *= DDenom;
    DDenom *= PI;
    float D = (alpha2 + EPSILON) / DDenom;
    return D;
}

float
Geometric(
        float specularRoughness,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH)
{
    float alpha = specularRoughness * specularRoughness;
    float k = alpha * 0.5;
    float G = NdotE / (NdotE * (1.0 - k) + k);
    G *= NdotL / (NdotL * (1.0 - k) + k);
    return G;
}

float3
evaluateDirectDiffuse()
{
    return float3(1.0 / PI);
}

float3
evaluateDirectSpecular(
        float3 specularColorF0,
        float3 specularColorF90,
        float specularRoughness,
        float fresnel,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH)
{
    float3 F = mix(specularColorF0, specularColorF90, fresnel);
    float D = NormalDistribution(specularRoughness, NdotH);
    float G = Geometric(specularRoughness, NdotL, NdotE, NdotH, EdotH);
    float3 RNum = F * G * D;
    float RDenom = 4.0f * NdotL * NdotE + EPSILON;
    return RNum / RDenom;
}

LightingContributions
usdPreviewSurfaceLighting(
        float3 diffuseColor,
        bool useSpecularWorkflow,
        float ior,
        float metallic,
        float specularAmount,
        float3 specularColor,
        float specularRoughness,
        float clearcoatAmount,
        float3 clearcoatColor,
        float clearcoatRoughness,
        float occlusion,
        float NdotL,
        float NdotE,
        float NdotH,
        float EdotH,
        float3 lightDiffuseIrradiance,
        float3 lightSpecularIrradiance)
{
    specularRoughness = max(0.001, specularRoughness);
    clearcoatRoughness = max(0.001, clearcoatRoughness);

    float fresnel = SchlickFresnel(EdotH);

    // Evaluate diffuse
    float3 d = diffuseColor * evaluateDirectDiffuse();

    // Evaluate specular first lobe
    float3 s1 = float3(0.0);
    if (specularAmount > 0.0) {
        float3 F0 = specularColor;
        float3 F90 = float3(1.0);

        if (!useSpecularWorkflow) {
            float R = (1.0 - ior) / (1.0 + ior);
            float3 specColor = mix(float3(1.0), diffuseColor, metallic);
            F0  = R * R * specColor;
            F90 = specColor;

            // For metallic workflows, pure metals have no diffuse
            d *= 1.0 - metallic;
        }

        s1 = specularAmount * evaluateDirectSpecular(
             F0,                          // Specular color 0
             F90,                         // Specular color 90
             specularRoughness,           // Roughness
             fresnel,                     // Fresnel
             NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights

        // Adjust the diffuse so glazing angles have less diffuse
        d *= (1.0 - mix(F0, F90, fresnel));
    }

    // Evaluate clearcoat
    float3 s2 = float3(0.0);
    if (clearcoatAmount > 0.0) {
        s2 = clearcoatAmount * evaluateDirectSpecular(
             clearcoatColor,              // Clearcoat color 0
             clearcoatColor,              // Clearcoat color 90
             clearcoatRoughness,          // Roughness
             fresnel,                     // Fresnel
             NdotL, NdotE, NdotH, EdotH); // Dot products needed for lights
    }

    LightingContributions lightingContrib;

    lightingContrib.diffuse =
        occlusion * NdotL * d * lightDiffuseIrradiance;

    lightingContrib.specular =
        occlusion * NdotL * (s1 + s2) * lightSpecularIrradiance;

    return lightingContrib;
}


]]>
            </source>
        </implementation>
    </implementation>
</fragment>