Rasagar/Library/PackageCache/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxFPathTracing.hlsl
2024-08-26 23:07:20 +03:00

123 lines
5.1 KiB
HLSL

#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingPayload.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingMaterial.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingBSDF.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingAOV.hlsl"
// AxF Material Data:
//
// bsdfWeight0 Diffuse BRDF
// bsdfWeight1 Clearoat BRDF
// bsdfWeight2 Specular BRDF(s)
float3 GetCoatNormal(MaterialData mtlData)
{
return mtlData.bsdfData.clearcoatNormalWS;
}
#ifdef _AXF_BRDF_TYPE_CAR_PAINT
float GetSpecularCoeffSum(MaterialData mtlData)
{
return mtlData.bsdfData.height_mm;
}
#endif
void ProcessBSDFData(PathPayload payload, BuiltinData builtinData, MaterialData mtlData, inout BSDFData bsdfData)
{
// Adjust roughness to reduce fireflies
bsdfData.roughness.x = max(payload.maxRoughness, bsdfData.roughness.x);
bsdfData.roughness.y = max(payload.maxRoughness, bsdfData.roughness.y);
#ifdef _AXF_BRDF_TYPE_CAR_PAINT
bsdfData.roughness.z = max(payload.maxRoughness, bsdfData.roughness.z);
#endif
// One of the killer features of AxF, optional specular Fresnel...
if (!HasFresnelTerm())
bsdfData.fresnel0 = 1.0;
// Make sure we can get valid coat normal reflection directions
if (HasClearcoat())
bsdfData.clearcoatNormalWS = ComputeConsistentShadingNormal(mtlData.V, bsdfData.geomNormalWS, bsdfData.clearcoatNormalWS);
#ifdef _AXF_BRDF_TYPE_CAR_PAINT
// We hijack height_mm, as it is not used here otherwise, to store the specular coefficients sum
bsdfData.height_mm = 0.0;
UNITY_UNROLL
for (uint i = 0; i < CARPAINT2_LOBE_COUNT; i++)
bsdfData.height_mm += _CarPaint2_CTCoeffs[i];
#endif
}
bool CreateMaterialData(PathPayload payload, BuiltinData builtinData, BSDFData bsdfData, inout float3 shadingPosition, inout float theSample, out MaterialData mtlData)
{
// Alter values in the material's bsdfData struct, to better suit path tracing
mtlData.V = -WorldRayDirection();
mtlData.Nv = ComputeConsistentShadingNormal(mtlData.V, bsdfData.geomNormalWS, bsdfData.normalWS);
mtlData.bsdfData = bsdfData;
ProcessBSDFData(payload, builtinData, mtlData, mtlData.bsdfData);
mtlData.bsdfWeight = 0.0;
// First determine if our incoming direction V is above (exterior) or below (interior) the surface
if (IsAbove(mtlData))
{
float NcoatdotV = dot(GetCoatNormal(mtlData), mtlData.V);
float NspecdotV = dot(GetSpecularNormal(mtlData), mtlData.V);
float Fcoat = F_Schlick(IorToFresnel0(bsdfData.clearcoatIOR), NcoatdotV);
float Fspec = Luminance(F_Schlick(mtlData.bsdfData.fresnel0, NspecdotV));
#if defined(_AXF_BRDF_TYPE_SVBRDF)
float specularCoeff = Luminance(mtlData.bsdfData.specularColor);
#elif defined(_AXF_BRDF_TYPE_CAR_PAINT)
float specularCoeff = GetSpecularCoeffSum(mtlData);
#endif
mtlData.bsdfWeight[1] = HasClearcoat() ? Fcoat * Luminance(mtlData.bsdfData.clearcoatColor) : 0.0;
float clearcoatTransmission = HasClearcoat() ? 1.0 - Fcoat : 1.0;
mtlData.bsdfWeight[2] = clearcoatTransmission * lerp(Fspec, 0.5, GetScalarRoughness(mtlData.bsdfData.roughness)) * specularCoeff;
mtlData.bsdfWeight[0] = clearcoatTransmission * Luminance(mtlData.bsdfData.diffuseColor) * max(mtlData.bsdfData.ambientOcclusion, 0.001);
}
// Normalize the weights
float wSum = mtlData.bsdfWeight[0] + mtlData.bsdfWeight[1] + mtlData.bsdfWeight[2];
if (wSum < BSDF_WEIGHT_EPSILON)
return false;
mtlData.bsdfWeight /= wSum;
return true;
}
#if defined(_AXF_BRDF_TYPE_SVBRDF)
# include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxFPathTracingSVBRDF.hlsl"
#elif defined(_AXF_BRDF_TYPE_CAR_PAINT)
# include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxFPathTracingCarPaint.hlsl"
#endif
float3 GetLightNormal(MaterialData mtlData)
{
// If both diffuse and specular normals are quasi-indentical, return one of them, otherwise return a null vector
return dot(GetDiffuseNormal(mtlData), GetSpecularNormal(mtlData)) > 0.99 ? GetDiffuseNormal(mtlData) : float3(0.0, 0.0, 0.0);
}
float AdjustPathRoughness(MaterialData mtlData, MaterialResult mtlResult, bool isSampleBelow, float pathRoughness)
{
// Adjust the max roughness, based on the estimated diff/spec ratio
float maxSpecRoughness = Max3(mtlData.bsdfData.roughness.x, mtlData.bsdfData.roughness.y, mtlData.bsdfData.roughness.z);
float adjustedPathRoughness = (mtlResult.specPdf * maxSpecRoughness + mtlResult.diffPdf) / (mtlResult.diffPdf + mtlResult.specPdf);
return adjustedPathRoughness;
}
float3 GetMaterialAbsorption(MaterialData mtlData, SurfaceData surfaceData, float dist, bool isSampleBelow)
{
// No absorption here
return 1.0;
}
void GetAOVData(BSDFData bsdfData, out AOVData aovData)
{
aovData.albedo = bsdfData.diffuseColor;
aovData.normal = bsdfData.normalWS;
}