您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
229 行
9.4 KiB
229 行
9.4 KiB
//-----------------------------------------------------------------------------
|
|
// SurfaceData and BSDFData
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// SurfaceData is define in Fabric.cs which generate Fabric.cs.hlsl
|
|
#include "Fabric.cs.hlsl"
|
|
#include "../Lit/SubsurfaceScatteringSettings.cs.hlsl"
|
|
|
|
#define WANT_SSS_CODE
|
|
#include "../LightEvaluationShare1.hlsl"
|
|
|
|
void FillMaterialIdStandardData(float3 baseColor, float specular, float metallic, float roughness, float3 normalWS, float3 tangentWS, float anisotropy, inout BSDFData bsdfData)
|
|
{
|
|
bsdfData.diffuseColor = baseColor * 0.5;
|
|
bsdfData.fresnel0 = baseColor;
|
|
|
|
// TODO: encode specular
|
|
|
|
bsdfData.tangentWS = tangentWS;
|
|
bsdfData.bitangentWS = cross(normalWS, tangentWS);
|
|
ConvertAnisotropyToRoughness(roughness, anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
|
|
bsdfData.anisotropy = 0.75;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// conversion function for forward
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BSDFData ConvertSurfaceDataToBSDFData(SurfaceData surfaceData)
|
|
{
|
|
ApplyDebugToSurfaceData(surfaceData);
|
|
|
|
BSDFData bsdfData;
|
|
ZERO_INITIALIZE(BSDFData, bsdfData);
|
|
|
|
bsdfData.specularOcclusion = surfaceData.specularOcclusion;
|
|
bsdfData.normalWS = surfaceData.normalWS;
|
|
bsdfData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness);
|
|
bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
|
|
bsdfData.materialId = surfaceData.materialId;
|
|
|
|
FillMaterialIdStandardData(surfaceData.baseColor, surfaceData.specular, 0, bsdfData.roughness, surfaceData.normalWS, surfaceData.tangentWS, surfaceData.anisotropy, bsdfData);
|
|
bsdfData.materialId = surfaceData.anisotropy > 0.0 ? MATERIALID_LIT_ANISO : bsdfData.materialId;
|
|
|
|
FillMaterialIdSSSData(surfaceData.baseColor, surfaceData.subsurfaceProfile, surfaceData.subsurfaceRadius, surfaceData.thickness, bsdfData);
|
|
|
|
return bsdfData;
|
|
}
|
|
|
|
float4 EncodeSplitLightingGBuffer0(SurfaceData surfaceData)
|
|
{
|
|
return float4(surfaceData.baseColor, 1.0);
|
|
}
|
|
|
|
float4 EncodeSplitLightingGBuffer1(SurfaceData surfaceData)
|
|
{
|
|
return float4(surfaceData.subsurfaceRadius, 1.0, 0.0, PackByte(surfaceData.subsurfaceProfile)); //TODO: Fabric UI
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// bake lighting function
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// GetBakedDiffuseLigthing function compute the bake lighting + emissive color to be store in emissive buffer (Deferred case)
|
|
// In forward it must be add to the final contribution.
|
|
// This function require the 3 structure surfaceData, builtinData, bsdfData because it may require both the engine side data, and data that will not be store inside the gbuffer.
|
|
float3 GetBakedDiffuseLigthing(SurfaceData surfaceData, BuiltinData builtinData, BSDFData bsdfData, PreLightData preLightData)
|
|
{
|
|
// Premultiply bake diffuse lighting information with DisneyDiffuse pre-integration
|
|
return builtinData.bakeDiffuseLighting * preLightData.diffuseFGD * surfaceData.ambientOcclusion * bsdfData.diffuseColor + builtinData.emissiveColor;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// light transport functions
|
|
//-----------------------------------------------------------------------------
|
|
|
|
LightTransportData GetLightTransportData(SurfaceData surfaceData, BuiltinData builtinData, BSDFData bsdfData)
|
|
{
|
|
LightTransportData lightTransportData;
|
|
|
|
// diffuseColor for lightmapping should basically be diffuse color.
|
|
// But rough metals (black diffuse) still scatter quite a lot of light around, so
|
|
// we want to take some of that into account too.
|
|
|
|
lightTransportData.diffuseColor = bsdfData.diffuseColor;
|
|
lightTransportData.emissiveColor = builtinData.emissiveColor;
|
|
|
|
return lightTransportData;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// LightLoop related function (Only include if required)
|
|
// HAS_LIGHTLOOP is define in Lighting.hlsl
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifdef HAS_LIGHTLOOP
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// BSDF share between directional light, punctual light and area light (reference)
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Note from Seb: The code was like that but it is in fact inverted... I haven't modify it to not break current data, but better to put it in correct order
|
|
#ifdef _FABRIC_SILK
|
|
#define BSDF BSDF_Silk
|
|
#else
|
|
#define BSDF BSDF_CottonWool
|
|
#endif
|
|
|
|
void BSDF_CottonWool(float3 V, float3 L, float3 positionWS, PreLightData preLightData, BSDFData bsdfData,
|
|
out float3 diffuseLighting,
|
|
out float3 specularLighting)
|
|
{
|
|
|
|
// Optimized math. Ref: PBR Diffuse Lighting for GGX + Smith Microsurfaces (slide 114).
|
|
float NdotL = saturate(dot(bsdfData.normalWS, L)); // Must have the same value without the clamp
|
|
float NdotV = preLightData.NdotV; // Get the unaltered (geometric) version
|
|
float LdotV = dot(L, V);
|
|
float invLenLV = rsqrt(abs(2 * LdotV + 2)); // invLenLV = rcp(length(L + V))
|
|
float NdotH = saturate((NdotL + NdotV) * invLenLV);
|
|
float LdotH = saturate(invLenLV * LdotV + invLenLV);
|
|
|
|
NdotV = max(NdotV, MIN_N_DOT_V); // Use the modified (clamped) version
|
|
|
|
float3 F = F_Schlick(0.2, LdotH);
|
|
|
|
float Vis;
|
|
float D_Velvet;//Ready at dawn cloth
|
|
// TODO: this way of handling aniso may not be efficient, or maybe with material classification, need to check perf here
|
|
// Maybe always using aniso maybe a win ?
|
|
float3 H = (L + V) * invLenLV;
|
|
bsdfData.roughness = 1- ClampRoughnessForAnalyticalLights(bsdfData.roughness);
|
|
float roughnessSq = bsdfData.roughness*bsdfData.roughness;
|
|
float N = 1.0 / (PI * (4.0 * roughnessSq + 1.0));
|
|
|
|
float NdotH2 = NdotH*NdotH;
|
|
float cotNdotH2 = NdotH2 / (1.000001 - NdotH2);
|
|
float sinNdotH2 = 1.0 - NdotH2;
|
|
D_Velvet = N * (1.0 + (4.0 * exp(-cotNdotH2 / roughnessSq) / max(sinNdotH2*sinNdotH2,1e-5)));
|
|
|
|
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
|
|
Vis = V_SmithJointGGX(NdotL, NdotV, bsdfData.roughness, preLightData.ggxLambdaV);
|
|
#else
|
|
Vis = V_SmithJointGGX(NdotL, NdotV, bsdfData.roughness);
|
|
#endif
|
|
|
|
float NdotLwrap = sqrt(NdotL);
|
|
|
|
specularLighting = NdotLwrap* F *Vis * D_Velvet *_FuzzTint;
|
|
|
|
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
|
|
float diffuseTerm = Lambert();
|
|
#elif LIT_DIFFUSE_GGX_BRDF
|
|
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.roughness);
|
|
#else
|
|
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotV, bsdfData.perceptualRoughness);
|
|
#endif
|
|
|
|
diffuseLighting = bsdfData.diffuseColor * diffuseTerm*lerp(1,0.5,bsdfData.roughness);
|
|
}
|
|
|
|
void BSDF_Silk(float3 V, float3 L, float3 positionWS, PreLightData preLightData, BSDFData bsdfData,
|
|
out float3 diffuseLighting,
|
|
out float3 specularLighting)
|
|
{
|
|
// Optimized math. Ref: PBR Diffuse Lighting for GGX + Smith Microsurfaces (slide 114).
|
|
float NdotL = saturate(dot(bsdfData.normalWS, L)); // Must have the same value without the clamp
|
|
float NdotV = preLightData.NdotV; // Get the unaltered (geometric) version
|
|
float LdotV = dot(L, V);
|
|
float invLenLV = rsqrt(abs(2 * LdotV + 2)); // invLenLV = rcp(length(L + V))
|
|
float NdotH = saturate((NdotL + NdotV) * invLenLV);
|
|
float LdotH = saturate(invLenLV * LdotV + invLenLV);
|
|
|
|
NdotV = max(NdotV, MIN_N_DOT_V); // Use the modified (clamped) version
|
|
|
|
float3 F = F_Schlick(bsdfData.fresnel0, LdotH);
|
|
|
|
float DV;
|
|
|
|
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
|
|
{
|
|
float3 H = (L + V) * invLenLV;
|
|
// For anisotropy we must not saturate these values
|
|
float TdotH = dot(bsdfData.tangentWS, H);
|
|
float TdotL = dot(bsdfData.tangentWS, L);
|
|
float BdotH = dot(bsdfData.bitangentWS, H);
|
|
float BdotL = dot(bsdfData.bitangentWS, L);
|
|
|
|
bsdfData.roughnessT = ClampRoughnessForAnalyticalLights(bsdfData.roughnessT);
|
|
bsdfData.roughnessB = ClampRoughnessForAnalyticalLights(bsdfData.roughnessB);
|
|
|
|
// TODO: Do comparison between this correct version and the one from isotropic and see if there is any visual difference
|
|
DV = DV_SmithJointGGXAniso(TdotH, BdotH, NdotH,
|
|
preLightData.TdotV, preLightData.BdotV, preLightData.NdotV,
|
|
TdotL, BdotL, NdotL,
|
|
bsdfData.roughnessT, bsdfData.roughnessB
|
|
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
|
|
, preLightData.partLambdaV);
|
|
#else
|
|
);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
bsdfData.roughness = ClampRoughnessForAnalyticalLights(bsdfData.roughness);
|
|
|
|
DV = DV_SmithJointGGX(NdotH, NdotL, NdotV, bsdfData.roughness
|
|
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
|
|
, preLightData partLambdaV);
|
|
#else
|
|
);
|
|
#endif
|
|
}
|
|
specularLighting = F * DV * _FuzzTint;
|
|
|
|
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
|
|
float diffuseTerm = Lambert();
|
|
#elif LIT_DIFFUSE_GGX_BRDF
|
|
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.roughness);
|
|
#else
|
|
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotV, bsdfData.perceptualRoughness);
|
|
#endif
|
|
|
|
diffuseLighting = bsdfData.diffuseColor * diffuseTerm;
|
|
}
|
|
|
|
#endif // #ifdef HAS_LIGHTLOOP
|
|
|
|
#include "../LightEvaluationShare2.hlsl"
|
|
|