You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
14 KiB
195 lines
14 KiB
void ApplyDecalToSurfaceDataNoNormal(DecalSurfaceData decalSurfaceData, inout SurfaceData surfaceData)
|
|
{
|
|
// using alpha compositing https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch23.html
|
|
surfaceData.baseColor.xyz = surfaceData.baseColor.xyz * decalSurfaceData.baseColor.w + decalSurfaceData.baseColor.xyz;
|
|
|
|
// TODOTODO: _MATERIAL_FEATURE_SPECULAR_COLOR and _MATERIAL_FEATURE_HAZY_GLOSS
|
|
|
|
#ifdef DECALS_4RT // only smoothness in 3RT mode
|
|
surfaceData.metallic = surfaceData.metallic * decalSurfaceData.MAOSBlend.x + decalSurfaceData.mask.x;
|
|
surfaceData.ambientOcclusion = surfaceData.ambientOcclusion * decalSurfaceData.MAOSBlend.y + decalSurfaceData.mask.y;
|
|
#endif
|
|
|
|
surfaceData.perceptualSmoothnessA = surfaceData.perceptualSmoothnessA * decalSurfaceData.mask.w + decalSurfaceData.mask.z;
|
|
surfaceData.perceptualSmoothnessB = surfaceData.perceptualSmoothnessB * decalSurfaceData.mask.w + decalSurfaceData.mask.z;
|
|
surfaceData.coatPerceptualSmoothness = surfaceData.coatPerceptualSmoothness * decalSurfaceData.mask.w + decalSurfaceData.mask.z;
|
|
}
|
|
|
|
|
|
void BuildSurfaceData(FragInputs fragInputs, inout SurfaceDescription surfaceDescription, float3 V, PositionInputs posInput, out SurfaceData surfaceData, out float3 bentNormalWS)
|
|
{
|
|
// setup defaults -- these are used if the graph doesn't output a value
|
|
ZERO_INITIALIZE(SurfaceData, surfaceData);
|
|
|
|
$CoatMaskOne: surfaceData.coatMask = 1.0;
|
|
$UseProfileIor: surfaceData.useProfileIor = true;
|
|
|
|
// Copy graph values to surfaceData, if defined
|
|
$SurfaceDescription.BaseColor: surfaceData.baseColor = surfaceDescription.BaseColor;
|
|
$SurfaceDescription.SubsurfaceMask: surfaceData.subsurfaceMask = surfaceDescription.SubsurfaceMask;
|
|
$SurfaceDescription.TransmissionTint: surfaceData.transmissionMask = surfaceDescription.TransmissionTint;
|
|
$SurfaceDescription.Thickness: surfaceData.thickness = surfaceDescription.Thickness;
|
|
$SurfaceDescription.DiffusionProfileHash: surfaceData.diffusionProfileHash = asuint(surfaceDescription.DiffusionProfileHash);
|
|
$SurfaceDescription.IridescenceMask: surfaceData.iridescenceMask = surfaceDescription.IridescenceMask;
|
|
$SurfaceDescription.IridescenceThickness: surfaceData.iridescenceThickness = surfaceDescription.IridescenceThickness;
|
|
$SurfaceDescription.IridescenceCoatFixupTIR: surfaceData.iridescenceCoatFixupTIR = surfaceDescription.IridescenceCoatFixupTIR;
|
|
$SurfaceDescription.IridescenceCoatFixupTIRClamp: surfaceData.iridescenceCoatFixupTIRClamp = surfaceDescription.IridescenceCoatFixupTIRClamp;
|
|
$SurfaceDescription.Specular: surfaceData.specularColor = surfaceDescription.Specular;
|
|
$SurfaceDescription.DielectricIor: surfaceData.dielectricIor = surfaceDescription.DielectricIor;
|
|
$SurfaceDescription.Metallic: surfaceData.metallic = surfaceDescription.Metallic;
|
|
$SurfaceDescription.Smoothness: surfaceData.perceptualSmoothnessA = surfaceDescription.Smoothness;
|
|
$SurfaceDescription.SmoothnessB: surfaceData.perceptualSmoothnessB = surfaceDescription.SmoothnessB;
|
|
$SurfaceDescription.Occlusion: surfaceData.ambientOcclusion = surfaceDescription.Occlusion;
|
|
//TODO: if custom external values are wanted, we would ideally need one SO value per lobe.
|
|
$SurfaceDescription.SpecularOcclusion: surfaceData.specularOcclusionCustomInput = surfaceDescription.SpecularOcclusion;
|
|
$SurfaceDescription.SOFixupVisibilityRatioThreshold: surfaceData.soFixupVisibilityRatioThreshold = surfaceDescription.SOFixupVisibilityRatioThreshold;
|
|
$SurfaceDescription.SOFixupStrengthFactor: surfaceData.soFixupStrengthFactor = surfaceDescription.SOFixupStrengthFactor;
|
|
$SurfaceDescription.SOFixupMaxAddedRoughness: surfaceData.soFixupMaxAddedRoughness = surfaceDescription.SOFixupMaxAddedRoughness;
|
|
|
|
$SurfaceDescription.Anisotropy: surfaceData.anisotropyA = surfaceDescription.Anisotropy;
|
|
$SurfaceDescription.AnisotropyB: surfaceData.anisotropyB = surfaceDescription.AnisotropyB;
|
|
$SurfaceDescription.CoatSmoothness: surfaceData.coatPerceptualSmoothness = surfaceDescription.CoatSmoothness;
|
|
$SurfaceDescription.CoatMask: surfaceData.coatMask = surfaceDescription.CoatMask;
|
|
$SurfaceDescription.CoatIor: surfaceData.coatIor = surfaceDescription.CoatIor;
|
|
$SurfaceDescription.CoatThickness: surfaceData.coatThickness = surfaceDescription.CoatThickness;
|
|
$SurfaceDescription.CoatExtinction: surfaceData.coatExtinction = surfaceDescription.CoatExtinction;
|
|
$SurfaceDescription.LobeMix: surfaceData.lobeMix = surfaceDescription.LobeMix;
|
|
$SurfaceDescription.Haziness: surfaceData.haziness = surfaceDescription.Haziness;
|
|
$SurfaceDescription.HazeExtent: surfaceData.hazeExtent = surfaceDescription.HazeExtent;
|
|
// Note: we don't know yet if we put 1.0 in surfaceData.hazyGlossMaxDielectricF0 or the graph provided value:
|
|
//$SurfaceDescription.HazyGlossMaxDielectricF0: surfaceData.hazyGlossMaxDielectricF0 = surfaceDescription.HazyGlossMaxDielectricF0;
|
|
|
|
// These static material feature allow compile time optimization
|
|
surfaceData.materialFeatures = MATERIALFEATUREFLAGS_STACK_LIT_STANDARD;
|
|
#ifdef _MATERIAL_FEATURE_SPECULAR_COLOR
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_STACK_LIT_SPECULAR_COLOR;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_DUAL_SPECULAR_LOBE
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_STACK_LIT_DUAL_SPECULAR_LOBE;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_HAZY_GLOSS
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_STACK_LIT_HAZY_GLOSS;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_ANISOTROPY
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_STACK_LIT_ANISOTROPY;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_COAT
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_STACK_LIT_COAT;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_COAT_NORMALMAP
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_STACK_LIT_COAT_NORMAL_MAP;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_IRIDESCENCE
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_STACK_LIT_IRIDESCENCE;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_SUBSURFACE_SCATTERING
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_STACK_LIT_SUBSURFACE_SCATTERING;
|
|
#endif
|
|
#ifdef _MATERIAL_FEATURE_TRANSMISSION
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_STACK_LIT_TRANSMISSION;
|
|
#endif
|
|
|
|
surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_SSS_DIFFUSE_POWER;
|
|
$UseProfileLobes: surfaceData.materialFeatures |= MATERIALFEATUREFLAGS_SSS_DUAL_LOBE;
|
|
|
|
#ifdef _MATERIAL_FEATURE_SPECULAR_COLOR
|
|
// Reproduce the energy conservation done in legacy Unity. Not ideal but better for compatibility and users can unchek it
|
|
$Specular.EnergyConserving: surfaceData.baseColor *= (1.0 - Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b));
|
|
#endif
|
|
|
|
#ifdef _MATERIAL_FEATURE_HAZY_GLOSS
|
|
surfaceData.hazyGlossMaxDielectricF0 = 1.0;
|
|
$CapHazinessIfNotMetallic: surfaceData.hazyGlossMaxDielectricF0 = surfaceDescription.HazyGlossMaxDielectricF0;
|
|
// ...no need for the SurfaceDescription.HazyGlossMaxDielectricF0: predicate,
|
|
// the CapHazinessIfNotMetallic: predicate is only active if the pass wants the PixelShaderSlot HazyGlossMaxDielectricF0
|
|
// and if masterNode.capHazinessWrtMetallic.isOn:, the later should ensure we're in hazygloss mode and thus,
|
|
// the masterNode has the HazyGlossMaxDielectricF0 material slot added.
|
|
#endif
|
|
|
|
//
|
|
// Setup all surfaceData normals: .normalWS, .bentNormalWS, .tangentWS, .coatNormalWS, .geomNormalWS
|
|
//
|
|
|
|
float3 doubleSidedConstants = GetDoubleSidedConstants();
|
|
|
|
ApplyDecalAndGetNormal(fragInputs, posInput, surfaceDescription, surfaceData);
|
|
|
|
surfaceData.geomNormalWS = fragInputs.tangentToWorld[2];
|
|
|
|
surfaceData.coatNormalWS = surfaceData.geomNormalWS;
|
|
$SurfaceDescription.CoatNormalOS: GetNormalWS_SrcOS(fragInputs, surfaceDescription.CoatNormalOS, surfaceData.coatNormalWS, doubleSidedConstants);
|
|
$SurfaceDescription.CoatNormalTS: GetNormalWS(fragInputs, surfaceDescription.CoatNormalTS, surfaceData.coatNormalWS, doubleSidedConstants);
|
|
$SurfaceDescription.CoatNormalWS: GetNormalWS_SrcWS(fragInputs, surfaceDescription.CoatNormalWS, surfaceData.CoatNormalWS, doubleSidedConstants);
|
|
|
|
// surfaceData.tangentWS = normalize(fragInputs.tangentToWorld[0].xyz);
|
|
// ...We don't need to normalize if we're going to call Orthonormalize anyways as long as
|
|
// surfaceData.normalWS is normalized:
|
|
surfaceData.tangentWS = (fragInputs.tangentToWorld[0].xyz); // The tangent is not normalize in tangentToWorld for mikkt. TODO: Check if it expected that we normalize with Morten. Tag: SURFACE_GRADIENT
|
|
|
|
$SurfaceDescription.TangentOS: surfaceData.tangentWS = TransformObjectToWorldNormal(surfaceDescription.TangentOS);
|
|
$SurfaceDescription.TangentTS: surfaceData.tangentWS = TransformTangentToWorld(surfaceDescription.TangentTS, fragInputs.tangentToWorld);
|
|
$SurfaceDescription.TangentWS: surfaceData.tangentWS = surfaceDescription.TangentWS;
|
|
|
|
surfaceData.bentNormalWS = float3(0.0, 0.0, 0.0); // Initialise bentNormalWS before decal to keep compiler quiet, will be override after decal.
|
|
|
|
bentNormalWS = surfaceData.normalWS;
|
|
$BentNormal: GetNormalWS(fragInputs, surfaceDescription.BentNormal, bentNormalWS, doubleSidedConstants);
|
|
surfaceData.bentNormalWS = bentNormalWS;
|
|
|
|
surfaceData.tangentWS = Orthonormalize(surfaceData.tangentWS, surfaceData.normalWS);
|
|
|
|
//
|
|
// SpecularAA
|
|
//
|
|
|
|
// TODO Note: specular occlusion that uses bent normals should also use filtering, although the visibility model is not a
|
|
// specular lobe with roughness but a cone with solid angle determined by the ambient occlusion so this is an even more
|
|
// empirical hack (with visibility modelled by a single circular region in direction space)
|
|
// Intuitively, an increase of variance should enlarge (possible) visibility and thus diminish the occlusion
|
|
// (enlarge the visibility cone). This goes in hand with the softer BSDF specular lobe.
|
|
|
|
// Note that when using the Hazy Gloss parametrization, the user has no direct control on smoothnessB, and
|
|
// surfaceData.perceptualSmoothnessB will be 0 in that case.
|
|
// Conceptually, in that mode smoothnessB now depends on hazeExtent and smoothnessA only, and hazeExtent is
|
|
// a perceptual control in that "smoothnessB from smoothnessA" dependency (it will also influence lobeMix and the new
|
|
// f0 for the base layer precisely via smoothnessB). Finally, in that parametrization, smoothnessB is always <= smoothnessA.
|
|
// It thus makes sense to only modify smoothnessA while doing SpecularAA, the hazemapping takes care of the rest.
|
|
// The compiler should prune out our calculations for surfaceData.perceptualSmoothnessB in that case since it will never
|
|
// be read before being overwritten later.
|
|
|
|
float geometricVariance = 0.0;
|
|
#if !defined(SHADER_STAGE_RAY_TRACING)
|
|
// Note Specular.AA: or Specular.GeometricAA: guarantees surfaceDescription has SpecularAAScreenSpaceVariance and SpecularAAThreshold.
|
|
$Specular.GeometricAA: geometricVariance = GeometricNormalVariance(fragInputs.tangentToWorld[2], surfaceDescription.SpecularAAScreenSpaceVariance);
|
|
#endif
|
|
// TODO: Handle normal map filtering
|
|
// Also handle texture normal filtering when we have the proper operator nodes and can thus have the variance port
|
|
// in our master node:
|
|
float textureFilteringVariance = 0.0;
|
|
//$NormalTexturtextureFiltering: textureFilteringVariance = DecodeVariance(surfaceDescription.CodedNormalVarianceMeasure);
|
|
float coatTextureFilteringVariance = 0.0;
|
|
//$NormalTexturtextureFiltering: coatTextureFilteringVariance = DecodeVariance(surfaceDescription.CodedCoatNormalVarianceMeasure);
|
|
|
|
#if defined(DEBUG_DISPLAY)
|
|
#if !defined(SHADER_STAGE_RAY_TRACING)
|
|
// Mipmap mode debugging isn't supported with ray tracing as it relies on derivatives
|
|
if (_DebugMipMapMode != DEBUGMIPMAPMODE_NONE)
|
|
{
|
|
#ifdef FRAG_INPUTS_USE_TEXCOORD0
|
|
surfaceData.baseColor = GET_TEXTURE_STREAMING_DEBUG(posInput.positionSS, fragInputs.texCoord0);
|
|
#else
|
|
surfaceData.baseColor = GET_TEXTURE_STREAMING_DEBUG_NO_UV(posInput.positionSS);
|
|
#endif
|
|
surfaceData.metallic = 0;
|
|
}
|
|
#endif
|
|
|
|
// We need to call ApplyDebugToSurfaceData after filling the surfaceData and before filling builtinData
|
|
// as it can modify attributes used for static lighting
|
|
ApplyDebugToSurfaceData(fragInputs.tangentToWorld, surfaceData);
|
|
#endif
|
|
|
|
$Specular.AA: surfaceData.perceptualSmoothnessA = NormalFiltering(surfaceData.perceptualSmoothnessA, geometricVariance + textureFilteringVariance, surfaceDescription.SpecularAAThreshold);
|
|
$Specular.AA: surfaceData.perceptualSmoothnessB = NormalFiltering(surfaceData.perceptualSmoothnessB, geometricVariance + textureFilteringVariance, surfaceDescription.SpecularAAThreshold);
|
|
$Specular.AA: surfaceData.coatPerceptualSmoothness = NormalFiltering(surfaceData.coatPerceptualSmoothness, geometricVariance + coatTextureFilteringVariance, surfaceDescription.SpecularAAThreshold);
|
|
}
|