浏览代码

Add SSS and transmission support to cloth + various cleanup/factor code

/main
Anis Benyoub 6 年前
当前提交
cb2c3076
共有 3 个文件被更改,包括 160 次插入80 次删除
  1. 5
      com.unity.render-pipelines.high-definition/HDRP/Material/Cloth/Cloth.cs
  2. 40
      com.unity.render-pipelines.high-definition/HDRP/Material/Cloth/Cloth.cs.hlsl
  3. 195
      com.unity.render-pipelines.high-definition/HDRP/Material/Cloth/Cloth.hlsl

5
com.unity.render-pipelines.high-definition/HDRP/Material/Cloth/Cloth.cs


ClothCottonWool = 1 << 0,
ClothSilk = 1 << 1,
ClothSubsurfaceScattering = 1 << 2,
CothTransmission = 1 << 3
ClothTransmission = 1 << 3
};
//-----------------------------------------------------------------------------

public Vector3 diffuseColor;
public Vector3 fresnel0;
public float ambientOcclusion;
public Vector3 fuzzTint;
[SurfaceDataAttributes(new string[] { "Normal WS", "Normal View Space" }, true)]
public Vector3 normalWS;

40
com.unity.render-pipelines.high-definition/HDRP/Material/Cloth/Cloth.cs.hlsl


#define MATERIALFEATUREFLAGS_CLOTH_COTTON_WOOL (1)
#define MATERIALFEATUREFLAGS_CLOTH_SILK (2)
#define MATERIALFEATUREFLAGS_CLOTH_SUBSURFACE_SCATTERING (4)
#define MATERIALFEATUREFLAGS_COTH_TRANSMISSION (8)
#define MATERIALFEATUREFLAGS_CLOTH_TRANSMISSION (8)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Cloth+SurfaceData: static fields

#define DEBUGVIEW_CLOTH_BSDFDATA_MATERIAL_FEATURES (1350)
#define DEBUGVIEW_CLOTH_BSDFDATA_DIFFUSE_COLOR (1351)
#define DEBUGVIEW_CLOTH_BSDFDATA_FRESNEL0 (1352)
#define DEBUGVIEW_CLOTH_BSDFDATA_SPECULAR_OCCLUSION (1353)
#define DEBUGVIEW_CLOTH_BSDFDATA_NORMAL_WS (1354)
#define DEBUGVIEW_CLOTH_BSDFDATA_NORMAL_VIEW_SPACE (1355)
#define DEBUGVIEW_CLOTH_BSDFDATA_PERCEPTUAL_ROUGHNESS (1356)
#define DEBUGVIEW_CLOTH_BSDFDATA_DIFFUSION_PROFILE (1357)
#define DEBUGVIEW_CLOTH_BSDFDATA_SUBSURFACE_MASK (1358)
#define DEBUGVIEW_CLOTH_BSDFDATA_THICKNESS (1359)
#define DEBUGVIEW_CLOTH_BSDFDATA_USE_THICK_OBJECT_MODE (1360)
#define DEBUGVIEW_CLOTH_BSDFDATA_TRANSMITTANCE (1361)
#define DEBUGVIEW_CLOTH_BSDFDATA_TANGENT_WS (1362)
#define DEBUGVIEW_CLOTH_BSDFDATA_BITANGENT_WS (1363)
#define DEBUGVIEW_CLOTH_BSDFDATA_ROUGHNESS_T (1364)
#define DEBUGVIEW_CLOTH_BSDFDATA_ROUGHNESS_B (1365)
#define DEBUGVIEW_CLOTH_BSDFDATA_ANISOTROPY (1366)
#define DEBUGVIEW_CLOTH_BSDFDATA_AMBIENT_OCCLUSION (1353)
#define DEBUGVIEW_CLOTH_BSDFDATA_SPECULAR_OCCLUSION (1354)
#define DEBUGVIEW_CLOTH_BSDFDATA_FUZZ_TINT (1355)
#define DEBUGVIEW_CLOTH_BSDFDATA_NORMAL_WS (1356)
#define DEBUGVIEW_CLOTH_BSDFDATA_NORMAL_VIEW_SPACE (1357)
#define DEBUGVIEW_CLOTH_BSDFDATA_PERCEPTUAL_ROUGHNESS (1358)
#define DEBUGVIEW_CLOTH_BSDFDATA_DIFFUSION_PROFILE (1359)
#define DEBUGVIEW_CLOTH_BSDFDATA_SUBSURFACE_MASK (1360)
#define DEBUGVIEW_CLOTH_BSDFDATA_THICKNESS (1361)
#define DEBUGVIEW_CLOTH_BSDFDATA_USE_THICK_OBJECT_MODE (1362)
#define DEBUGVIEW_CLOTH_BSDFDATA_TRANSMITTANCE (1363)
#define DEBUGVIEW_CLOTH_BSDFDATA_TANGENT_WS (1364)
#define DEBUGVIEW_CLOTH_BSDFDATA_BITANGENT_WS (1365)
#define DEBUGVIEW_CLOTH_BSDFDATA_ROUGHNESS_T (1366)
#define DEBUGVIEW_CLOTH_BSDFDATA_ROUGHNESS_B (1367)
#define DEBUGVIEW_CLOTH_BSDFDATA_ANISOTROPY (1368)
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.Cloth+SurfaceData
// PackingRules = Exact

uint materialFeatures;
float3 diffuseColor;
float3 fresnel0;
float ambientOcclusion;
float3 fuzzTint;
float3 normalWS;
float perceptualRoughness;
uint diffusionProfile;

case DEBUGVIEW_CLOTH_BSDFDATA_FRESNEL0:
result = bsdfdata.fresnel0;
break;
case DEBUGVIEW_CLOTH_BSDFDATA_AMBIENT_OCCLUSION:
result = bsdfdata.ambientOcclusion.xxx;
break;
break;
case DEBUGVIEW_CLOTH_BSDFDATA_FUZZ_TINT:
result = bsdfdata.fuzzTint;
break;
case DEBUGVIEW_CLOTH_BSDFDATA_NORMAL_WS:
result = bsdfdata.normalWS * 0.5 + 0.5;

195
com.unity.render-pipelines.high-definition/HDRP/Material/Cloth/Cloth.hlsl


//-----------------------------------------------------------------------------
// SurfaceData is defined in Cloth.cs which generates Cloth.cs.hlsl
#include "Cloth.cs.hlsl"
// Those define allow to include desired SSS/Transmission functions
#define MATERIAL_INCLUDE_SUBSURFACESCATTERING
#define MATERIAL_INCLUDE_TRANSMISSION
#include "HDRP/Material/SubsurfaceScattering/SubsurfaceScattering.hlsl"
#include "HDRP/Material/NormalBuffer.hlsl"
#include "CoreRP/ShaderLibrary/VolumeRendering.hlsl"
//-----------------------------------------------------------------------------
// Texture and constant buffer declaration
//-----------------------------------------------------------------------------
#include "HDRP/Material/LTCAreaLight/LTCAreaLight.hlsl"
#include "HDRP/Material/PreIntegratedFGD/PreIntegratedFGD.hlsl"
//-----------------------------------------------------------------------------
// Helper functions/variable specific to this material
//-----------------------------------------------------------------------------
// Assume bsdfData.normalWS is init
void FillMaterialAnisotropy(float anisotropy, float3 tangentWS, float3 bitangentWS, inout BSDFData bsdfData)
{
bsdfData.anisotropy = anisotropy;
bsdfData.tangentWS = tangentWS;
bsdfData.bitangentWS = bitangentWS;
}
// This function is use to help with debugging and must be implemented by any lit material
// Implementer must take into account what are the current override component and

if (overrideSmoothness)
{
//float overrideSmoothnessValue = _DebugLightingSmoothness.y;
//surfaceData.perceptualSmoothness = overrideSmoothnessValue;
float overrideSmoothnessValue = _DebugLightingSmoothness.y;
surfaceData.perceptualSmoothness = overrideSmoothnessValue;
}
if (overrideNormal)

#ifdef DEBUG_DISPLAY
// Override value if requested by user
// this can be use also in case of debug lighting mode like specular only
//bool overrideSpecularColor = _DebugLightingSpecularColor.x != 0.0;
bool overrideSpecularColor = _DebugLightingSpecularColor.x != 0.0;
//if (overrideSpecularColor)
//{
// float3 overrideSpecularColor = _DebugLightingSpecularColor.yzw;
// bsdfData.fresnel0 = overrideSpecularColor;
//}
if (overrideSpecularColor)
{
float3 overrideSpecularColor = _DebugLightingSpecularColor.yzw;
bsdfData.fresnel0 = overrideSpecularColor;
}
#endif
}

// However in practice we keep parity between deferred and forward, so we should constrain the various features.
// The UI is in charge of setuping the constrain, not the code. So if users is forward only and want unleash power, it is easy to unleash by some UI change
if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_SUBSURFACE_SCATTERING))
if (HasFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_SUBSURFACE_SCATTERING))
if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_COTH_TRANSMISSION))
if (HasFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_TRANSMISSION))
if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_SILK))
if (HasFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_SILK))
// roughnessT and roughnessB are clamped, and are meant to be used with punctual and directional lights.
// perceptualRoughness is not clamped, and is meant to be used for IBL.
// perceptualRoughness can be modify by FillMaterialClearCoatData, so ConvertAnisotropyToClampRoughness must be call after
ConvertAnisotropyToClampRoughness(bsdfData.perceptualRoughness, bsdfData.anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
bsdfData.fresnel0 = HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_LIT_SPECULAR_COLOR) ? surfaceData.specularColor : ComputeFresnel0(surfaceData.baseColor, surfaceData.metallic, DEFAULT_SPECULAR_VALUE);
ApplyDebugToBSDFData(bsdfData);
ApplyDebugToBSDFData(bsdfData);
return bsdfData;
}

GetGeneratedBSDFDataDebug(paramId, bsdfData, result, needLinearToSRGB);
}
//-----------------------------------------------------------------------------
// PreLightData
//

{
float NdotV; // Could be negative due to normal mapping, use ClampNdotV()
float partLambdaV;
// IBL
float3 iblR; // Reflected specular direction, used for IBL in EvaluateBSDF_Env()
float iblPerceptualRoughness;
float3 specularFGD; // Store preintegrated BSDF for both specular and diffuse
float diffuseFGD;
};
// This function is call to precompute heavy calculation before lightloop

float3 N = bsdfData.normalWS;
preLightData.NdotV = dot(N, V);
preLightData.iblPerceptualRoughness = bsdfData.perceptualRoughness;
// We avoid divergent evaluation of the GGX, as that nearly doubles the cost.
// If the tile has anisotropy, all the pixels within the tile are evaluated as anisotropic.
if (HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_SILK))
float unused;
float3 iblN;
// Reminder: This is a static if resolve at compile time
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_SILK))
// See code in lit.hlsl - TODO: share!
//float3 grainDirWS = (bsdfData.anisotropy >= 0.0) ? bsdfData.bitangentWS : bsdfData.tangentWS;
//float stretch = abs(bsdfData.anisotropy) * saturate(5 * preLightData.iblPerceptualRoughness);
//iblN = GetAnisotropicModifiedNormal(grainDirWS, N, V, stretch);
// For GGX aniso and IBL we have done an empirical (eye balled) approximation compare to the reference.
// We use a single fetch, and we stretch the normal to use based on various criteria.
// result are far away from the reference but better than nothing
// For positive anisotropy values: tangent = highlight stretch (anisotropy) direction, bitangent = grain (brush) direction.
float3 grainDirWS = (bsdfData.anisotropy >= 0.0) ? bsdfData.bitangentWS : bsdfData.tangentWS;
// Reduce stretching for (perceptualRoughness < 0.2).
float stretch = abs(bsdfData.anisotropy) * saturate(5 * preLightData.iblPerceptualRoughness);
// NOTE: If we follow the theory we should use the modified normal for the different calculation implying a normal (like NdotV) and use 'anisoIblNormalWS'
// into function like GetSpecularDominantDir(). However modified normal is just a hack. The goal is just to stretch a cubemap, no accuracy here.
// With this in mind and for performance reasons we chose to only use modified normal to calculate R.
iblN = GetAnisotropicModifiedNormal(grainDirWS, N, V, stretch);
GetPreIntegratedFGDGGXAndDisneyDiffuse(NdotV, preLightData.iblPerceptualRoughness, bsdfData.fresnel0, preLightData.specularFGD, preLightData.diffuseFGD, unused);
// This is a ad-hoc tweak to better match reference of anisotropic GGX.
// TODO: We need a better hack.
preLightData.iblPerceptualRoughness *= saturate(1.2 - abs(bsdfData.anisotropy));
preLightData.partLambdaV = 0;
//iblN = N;
preLightData.partLambdaV = 0.0;
iblN = N;
GetPreIntegratedFGDCharlieAndClothLambert(NdotV, preLightData.iblPerceptualRoughness, bsdfData.fresnel0, preLightData.specularFGD, preLightData.diffuseFGD, unused);
preLightData.iblR = reflect(-V, iblN);
return preLightData;
}

}
#endif
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_SUBSURFACE_SCATTERING)) // This test is static as it is done in GBuffer or forward pass, will be remove by compiler
{
bsdfData.diffuseColor = GetModifiedDiffuseColorForSSS(bsdfData); // local modification of bsdfData
}
//return builtinData.bakeDiffuseLighting * preLightData.diffuseFGD * surfaceData.ambientOcclusion * bsdfData.diffuseColor + builtinData.emissiveColor;
return builtinData.bakeDiffuseLighting * bsdfData.diffuseColor;
return builtinData.bakeDiffuseLighting * preLightData.diffuseFGD * surfaceData.ambientOcclusion * bsdfData.diffuseColor + builtinData.emissiveColor;
}

{
LightTransportData lightTransportData;
// diffuseColor for lightmapping
// DiffuseColor for lightmapping
lightTransportData.diffuseColor = bsdfData.diffuseColor;
lightTransportData.emissiveColor = builtinData.emissiveColor;

// Cloth are dieletric but we simulate forward scattering effect with colored specular (fuzz tint term)
float3 F = F_Schlick(bsdfData.fresnel0, LdotH);
if (HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_COTTON_WOOL))
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_COTTON_WOOL))
{
float D = D_Charlie(NdotH, bsdfData.roughnessT);
// V_Charlie is expensive, use approx with V_Ashikhmin instead

DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
float3 N = bsdfData.normalWS;
float3 L = -lightData.forward; // Lights point backward in Unity
float NdotL = dot(N, L);
float3 L = -lightData.forward;
float3 N = bsdfData.normalWS;
float NdotL = dot(N, L);
float3 transmittance = float3(0.0, 0.0, 0.0);
if (HasFlag(bsdfData.materialFeatures, MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_THIN_THICKNESS))
{
// Caution: This function modify N and contactShadowIndex
transmittance = PreEvaluateDirectionalLightTransmission(NdotL, lightData, bsdfData, N, lightData.contactShadowIndex); // contactShadowIndex is only modify for the code of this function
}
// color and attenuation are outputted by EvaluateLight:
float3 color;
float attenuation;
EvaluateLight_Directional(lightLoopContext, posInput, lightData, bakeLightingData, N, L, color, attenuation);

lighting.specular *= intensity * lightData.specularScale;
}
// The mixed thickness mode is not supported by directional lights due to poor quality and high performance impact.
if (HasFlag(bsdfData.materialFeatures, MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_THIN_THICKNESS))
{
float NdotV = ClampNdotV(preLightData.NdotV);
float LdotV = dot(L, V);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
lighting.diffuse += EvaluateTransmission(bsdfData, transmittance, NdotL, NdotV, LdotV, attenuation * lightData.diffuseScale);
}
// Save ALU by applying light and cookie colors only once.
lighting.diffuse *= color;
lighting.specular *= color;

DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
float3 lightToSample = posInput.positionWS - lightData.positionWS;
int lightType = lightData.lightType;
float3 lightToSample;
distances.w = dot(lightToSample, lightData.forward);
GetPunctualLightVectors(posInput.positionWS, lightData, L, lightToSample, distances);
float3 N = bsdfData.normalWS;
float NdotL = dot(N, L);
if (lightType == GPULIGHTTYPE_PROJECTOR_BOX)
{
L = -lightData.forward;
distances.xyz = 1; // No distance or angle attenuation
}
else
float3 transmittance = float3(0.0, 0.0, 0.0);
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_TRANSMISSION))
float3 unL = -lightToSample;
float distSq = dot(unL, unL);
float distRcp = rsqrt(distSq);
float dist = distSq * distRcp;
L = unL * distRcp;
distances.xyz = float3(dist, distSq, distRcp);
// Caution: This function modify N and lightData.contactShadowIndex
transmittance = PreEvaluatePunctualLightTransmission(lightLoopContext, posInput, distances.x, NdotL, L, bsdfData, N, lightData);
float3 N = bsdfData.normalWS;
float NdotV = ClampNdotV(preLightData.NdotV);
float NdotL = dot(N, L);
float LdotV = dot(L, V);
// Shader implementer is free to use minRoughness paramter or not(But better if it is done)
//bsdfData.coatRoughness = max(bsdfData.coatRoughness, lightData.minRoughness);
//bsdfData.roughnessT = max(bsdfData.roughnessT, lightData.minRoughness);
//bsdfData.roughnessB = max(bsdfData.roughnessB, lightData.minRoughness);
bsdfData.roughnessT = max(bsdfData.roughnessT, lightData.minRoughness);
bsdfData.roughnessB = max(bsdfData.roughnessB, lightData.minRoughness);
BSDF(V, L, NdotL, posInput.positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular);

// Save ALU by applying light and cookie colors only once.
lighting.diffuse *= color;
lighting.specular *= color;
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_CLOTH_TRANSMISSION))
{
float NdotV = ClampNdotV(preLightData.NdotV);
float LdotV = dot(L, V);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
lighting.diffuse += EvaluateTransmission(bsdfData, transmittance, NdotL, NdotV, LdotV, attenuation * lightData.diffuseScale);
}
#ifdef DEBUG_DISPLAY
if (_DebugLightingMode == DEBUGLIGHTINGMODE_LUX_METER)

out float3 diffuseLighting, out float3 specularLighting)
{
AmbientOcclusionFactor aoFactor;
GetScreenSpaceAmbientOcclusion(posInput.positionSS, preLightData.NdotV, 1.0, 1.0, 1.0, aoFactor);
GetScreenSpaceAmbientOcclusionMultibounce(posInput.positionSS, preLightData.NdotV, bsdfData.perceptualRoughness, bsdfData.ambientOcclusion, bsdfData.specularOcclusion, bsdfData.diffuseColor, bsdfData.fresnel0, aoFactor);
// Apply the albedo to the direct diffuse lighting and that's about it.
// Subsurface scattering mode
float3 modifiedDiffuseColor = GetModifiedDiffuseColorForSSS(bsdfData);
// Apply the albedo to the direct diffuse lighting (only once). The indirect (baked)
diffuseLighting = bsdfData.diffuseColor * lighting.direct.diffuse + bakeLightingData.bakeDiffuseLighting;
diffuseLighting = modifiedDiffuseColor * lighting.direct.diffuse + bakeLightingData.bakeDiffuseLighting;
specularLighting = lighting.direct.specular + lighting.indirect.specularReflected;
#ifdef DEBUG_DISPLAY

正在加载...
取消
保存