Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HDRP] AxF RTR: fix performance mode distillation that was broken #6104

Merged
merged 1 commit into from
Nov 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ public struct BSDFData

[SurfaceDataAttributes(new string[] { "Geometric Normal", "Geometric Normal View Space" }, true, checkIsNormalized = true)]
public Vector3 geomNormalWS;

// Needed for raytracing.
// TODO: should just modify FitToStandardLit in ShaderPassRaytracingGBuffer.hlsl and callee
// to have "V" (from -incidentDir)
[SurfaceDataAttributes("View Direction", true)]
public Vector3 viewWS;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as it is a vector, needs the suface data attributes for the vectors, check geomNormalWS

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is currently ok. No need for more debug mode for this one.

};

//-----------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
#define DEBUGVIEW_AXF_BSDFDATA_CLEARCOAT_IOR (1277)
#define DEBUGVIEW_AXF_BSDFDATA_GEOMETRIC_NORMAL (1278)
#define DEBUGVIEW_AXF_BSDFDATA_GEOMETRIC_NORMAL_VIEW_SPACE (1279)
#define DEBUGVIEW_AXF_BSDFDATA_VIEW_DIRECTION (1280)

// Generated from UnityEngine.Rendering.HighDefinition.AxF+SurfaceData
// PackingRules = Exact
Expand Down Expand Up @@ -152,6 +153,7 @@ struct BSDFData
float3 clearcoatNormalWS;
float clearcoatIOR;
float3 geomNormalWS;
float3 viewWS;
};

//
Expand Down Expand Up @@ -356,6 +358,9 @@ void GetGeneratedBSDFDataDebug(uint paramId, BSDFData bsdfdata, inout float3 res
case DEBUGVIEW_AXF_BSDFDATA_GEOMETRIC_NORMAL_VIEW_SPACE:
result = IsNormalized(bsdfdata.geomNormalWS)? bsdfdata.geomNormalWS * 0.5 + 0.5 : float3(1.0, 0.0, 0.0);
break;
case DEBUGVIEW_AXF_BSDFDATA_VIEW_DIRECTION:
result = bsdfdata.viewWS * 0.5 + 0.5;
break;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ float3 GetColorBaseFresnelF0(BSDFData bsdfData)

// For raytracing fit to standard Lit:
// Giving V will use a codepath where V is used, otherwise, the ortho direction is used
void GetCarPaintSpecularColorAndFlakesComponent(SurfaceData surfaceData, out float3 singleBRDFColor, out float3 singleFlakesComponent, out float coatFGD, float3 V = 0)
void GetCarPaintSpecularColorAndFlakesComponent(BSDFData bsdfData, out float3 singleBRDFColor, out float3 singleFlakesComponent, out float coatFGD, float3 V = 0)
{
//TODO: use approximated top lobe dir (if refractive coat) to have more appropriate and consistent base dirs

Expand All @@ -894,38 +894,95 @@ void GetCarPaintSpecularColorAndFlakesComponent(SurfaceData surfaceData, out flo

if (useViewDir)
{
float3 coatNormalWS = HasClearcoat() ? surfaceData.clearcoatNormalWS : surfaceData.normalWS;
float3 coatNormalWS = HasClearcoat() ? bsdfData.clearcoatNormalWS : bsdfData.normalWS;
float coatNdotV = dot(coatNormalWS, V);
coatFGD = HasClearcoat() ? F_FresnelDieletricSafe(surfaceData.clearcoatIOR, coatNdotV) : 0;
coatFGD = HasClearcoat() ? F_FresnelDieletricSafe(bsdfData.clearcoatIOR, coatNdotV) : 0;

float3 refractedViewWS = V;
float thetaHForBRDFColor = FixedBRDFColorThetaHForIndirectLight;
float thetaHForFlakes = FixedFlakesThetaHForIndirectLight;
if (HasClearcoatAndRefraction())
{
refractedViewWS = -Refract(V, coatNormalWS, 1.0 / surfaceData.clearcoatIOR);
thetaHForBRDFColor = Refract(thetaHForBRDFColor, 1.0 / surfaceData.clearcoatIOR);
thetaHForFlakes = Refract(thetaHForFlakes, 1.0 / surfaceData.clearcoatIOR);
refractedViewWS = -Refract(V, coatNormalWS, 1.0 / bsdfData.clearcoatIOR);
thetaHForBRDFColor = Refract(thetaHForBRDFColor, 1.0 / bsdfData.clearcoatIOR);
thetaHForFlakes = Refract(thetaHForFlakes, 1.0 / bsdfData.clearcoatIOR);
}
float NdotV = dot(surfaceData.normalWS, refractedViewWS);
float NdotV = dot(bsdfData.normalWS, refractedViewWS);

float thetaH = 0; //FastACosPos(clamp(NdotH, 0, 1));
float thetaD = FastACosPos(clamp(NdotV, 0, 1));

singleBRDFColor = GetBRDFColor(thetaHForBRDFColor, thetaD);
singleFlakesComponent = CarPaint_BTF(thetaHForFlakes, thetaD, surfaceData, (BSDFData)0, /*useBSDFData:*/false);
singleFlakesComponent = CarPaint_BTF(thetaHForFlakes, thetaD, (SurfaceData)0, bsdfData, /*useBSDFData:*/true);
}
else
{
//coatFGD = HasClearcoat() ? F_FresnelDieletricSafe(surfaceData.clearcoatIOR, 1) : 0;
// ...this is just F0 of coat, so we do the equivalent:
coatFGD = HasClearcoat() ? IorToFresnel0(surfaceData.clearcoatIOR) : 0;
coatFGD = HasClearcoat() ? IorToFresnel0(bsdfData.clearcoatIOR) : 0;

singleBRDFColor = GetBRDFColor(0,0);
singleFlakesComponent = CarPaint_BTF(0, 0, surfaceData, (BSDFData)0, /*useBSDFData:*/false);
singleFlakesComponent = CarPaint_BTF(0, 0,(SurfaceData)0, bsdfData, /*useBSDFData:*/true);
}
}

// For raytracing fit to standard Lit:
// Giving V will use a codepath where V is used, this is relevant only for carpaint model
// (cf GetColorBaseDiffuse() and GetColorBaseFresnelF0())
void GetBaseSurfaceColorAndF0(BSDFData bsdfData, out float3 diffuseColor, out float3 fresnel0, out float3 specBRDFColor, out float3 singleFlakesComponent, out float coatFGD, float3 V = 0, bool mixFlakes = false)
{
coatFGD = 0;
singleFlakesComponent = (float3)0;
fresnel0 = (float3)0;
float3 specularColor = (float3)0;
specBRDFColor = float3(1,1,1); // only used for carpaint
diffuseColor = bsdfData.diffuseColor;

#ifdef _AXF_BRDF_TYPE_SVBRDF

specularColor = bsdfData.specularColor;
fresnel0 = bsdfData.fresnel0; // See AxfData.hlsl: the actual sampled texture is always 1 channel, if we ever find otherwise, we will use the others.
fresnel0 = HasFresnelTerm() ? fresnel0.r * specularColor : specularColor;

#elif defined(_AXF_BRDF_TYPE_CAR_PAINT)

GetCarPaintSpecularColorAndFlakesComponent(bsdfData, /*out*/specBRDFColor, /*out*/singleFlakesComponent, /*out*/coatFGD, V);

// For carpaint, diffuseColor is not chromatic.
// A chromatic diffuse albedo is the result of a scalar diffuse coefficient multiplied by the brdf color table value.
specularColor = specBRDFColor;
diffuseColor *= specBRDFColor;
fresnel0 = saturate(3*bsdfData.fresnel0);//GetCarPaintFresnel0() TODO: presumably better fit using V, see also GetCarPaintSpecularColor that uses V
fresnel0 = fresnel0.r * specularColor;

if (mixFlakes)
{
float maxf0 = Max3(fresnel0.r, fresnel0.g, fresnel0.b);
fresnel0 = saturate(singleFlakesComponent + fresnel0);
}

#endif

float baseEnergy = (1-coatFGD); // should be Sq but at this point we eyeball anyway,
//specularColor *= baseEnergy;
//diffuseColor *= baseEnergy;
//...commented, seems better without it.
}

void GetRoughnessNormalCoatMaskForFitToStandardLit(BSDFData bsdfData, float coatFGD, out float3 normalWS, out float roughness, out float coatMask)
{
normalWS = bsdfData.normalWS; // todo: "refract back" hack
// Try to simulate apparent roughness increase when he have refraction as we can't store refracted V in the GBUFFER,
// we could try another hack and modify the normal too.
roughness = GetScalarRoughness(bsdfData.roughness);
roughness = saturate(roughness * (HasClearcoatAndRefraction() ? (max(1, bsdfData.clearcoatIOR)) : 1) );
coatMask = HasClearcoat()? Sq(coatFGD) * Max3(bsdfData.clearcoatColor.r, bsdfData.clearcoatColor.g, bsdfData.clearcoatColor.b) : 0;
// Sq(coatFGD) is a hack to better fit what AxF shows vs the usage of the coatmask with Lit
coatMask = 0;
//...disable for now coat reduces too much visibility of primary surface and in any case in performance mode where we use FitToStandardLit,
//we will not get another reflection bounce so the coat reflection will be a fallback probe
}

float3 GetColorBaseDiffuse(BSDFData bsdfData)
{
float3 diffuseColor = 0;
Expand Down Expand Up @@ -1212,6 +1269,10 @@ BSDFData ConvertSurfaceDataToBSDFData(uint2 positionSS, SurfaceData surfaceData)
bsdfData.ambientOcclusion = surfaceData.ambientOcclusion;
bsdfData.specularOcclusion = surfaceData.specularOcclusion;

// V is needed for raytracing performance fit to lit:
// TODO: should just modify FitToStandardLit in ShaderPassRaytracingGBuffer.hlsl and callee
// to have "V" (from -incidentDir)
bsdfData.viewWS = surfaceData.viewWS;
bsdfData.normalWS = surfaceData.normalWS;
bsdfData.tangentWS = surfaceData.tangentWS;
bsdfData.bitangentWS = cross(bsdfData.normalWS, bsdfData.tangentWS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,29 @@ void FitToStandardLit( BSDFData bsdfData
, uint2 positionSS
, out StandardBSDFData outStandardlit)
{
float3 specBRDFColor; // for carpaint, will be white otherwise
float3 singleFlakesComponent;
float scalarRoughness;
float coatFGD;

// We can fake flakes by mixing a component in the diffuse color
// or the F0, with the later maybe averaging the f0 according to roughness and V
GetBaseSurfaceColorAndF0(bsdfData,
/*out*/ outStandardlit.baseColor,
/*out*/ outStandardlit.fresnel0,
/*out*/specBRDFColor,
/*out*/singleFlakesComponent,
/*out*/coatFGD,
bsdfData.viewWS,
/*mixFlakes:*/ true);

outStandardlit.specularOcclusion = bsdfData.specularOcclusion;
outStandardlit.normalWS = bsdfData.normalWS;
outStandardlit.baseColor = bsdfData.diffuseColor;
outStandardlit.fresnel0 = bsdfData.specularColor;
outStandardlit.perceptualRoughness = bsdfData.perceptualRoughness;
outStandardlit.coatMask = 0;
outStandardlit.emissiveAndBaked = builtinData.bakeDiffuseLighting * bsdfData.specularColor * bsdfData.ambientOcclusion + builtinData.emissiveColor;

GetRoughnessNormalCoatMaskForFitToStandardLit(bsdfData, coatFGD, /*out*/ outStandardlit.normalWS, /*out*/ scalarRoughness, /*out*/ outStandardlit.coatMask);
outStandardlit.perceptualRoughness = RoughnessToPerceptualRoughness(scalarRoughness);

// diffuseFGD is one (from Lambert), but carpaint have a tint on diffuse, try to fit that here:
outStandardlit.emissiveAndBaked = builtinData.bakeDiffuseLighting * specBRDFColor * bsdfData.ambientOcclusion + builtinData.emissiveColor;
outStandardlit.isUnlit = 0;
}
#endif