您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
366 行
15 KiB
366 行
15 KiB
#ifndef UNITY_MATERIAL_LIT_INCLUDED
|
|
#define UNITY_MATERIAL_LIT_INCLUDED
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// SurfaceData and BSDFData
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// SurfaceData is define in Lit.cs which generate Lit.cs.hlsl
|
|
#include "Lit.cs.hlsl"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// conversion function for forward
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BSDFData ConvertSurfaceDataToBSDFData(SurfaceData surfaceData)
|
|
{
|
|
BSDFData bsdfData = (BSDFData)0;
|
|
|
|
bsdfData.specularOcclusion = surfaceData.specularOcclusion;
|
|
bsdfData.normalWS = surfaceData.normalWS;
|
|
bsdfData.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness);
|
|
bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
|
|
bsdfData.materialId = surfaceData.materialId;
|
|
|
|
if (bsdfData.materialId == MATERIALID_LIT_STANDARD)
|
|
{
|
|
bsdfData.diffuseColor = surfaceData.baseColor * (1.0 - surfaceData.metalic);
|
|
bsdfData.fresnel0 = lerp(float3(surfaceData.specular, surfaceData.specular, surfaceData.specular), surfaceData.baseColor, surfaceData.metalic);
|
|
|
|
bsdfData.tangentWS = surfaceData.tangentWS;
|
|
bsdfData.bitangentWS = cross(surfaceData.normalWS, surfaceData.tangentWS);
|
|
ConvertAnisotropyToRoughness(bsdfData.roughness, surfaceData.anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
|
|
}
|
|
else if (bsdfData.materialId == MATERIALID_LIT_SSS)
|
|
{
|
|
bsdfData.diffuseColor = surfaceData.baseColor;
|
|
bsdfData.fresnel0 = 0.028; // TODO take from subSurfaceProfile
|
|
bsdfData.subSurfaceRadius = surfaceData.subSurfaceRadius;
|
|
bsdfData.thickness = surfaceData.thickness;
|
|
bsdfData.subSurfaceProfile = surfaceData.subSurfaceProfile;
|
|
}
|
|
else if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT)
|
|
{
|
|
bsdfData.diffuseColor = surfaceData.baseColor * (1.0 - surfaceData.metalic);
|
|
bsdfData.fresnel0 = lerp(float3(surfaceData.specular, surfaceData.specular, surfaceData.specular), surfaceData.baseColor, surfaceData.metalic);
|
|
bsdfData.coatNormalWS = surfaceData.coatNormalWS;
|
|
bsdfData.coatRoughness = PerceptualSmoothnessToRoughness(surfaceData.coatPerceptualSmoothness);
|
|
}
|
|
else if (bsdfData.materialId == MATERIALID_LIT_SPECULAR)
|
|
{
|
|
bsdfData.diffuseColor = surfaceData.baseColor;
|
|
bsdfData.fresnel0 = surfaceData.specularColor;
|
|
}
|
|
|
|
return bsdfData;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Packing helper functions specific to this surfaceData
|
|
//-----------------------------------------------------------------------------
|
|
|
|
float PackMaterialId(int materialId)
|
|
{
|
|
return float(materialId) / 3.0;
|
|
}
|
|
|
|
int UnpackMaterialId(float f)
|
|
{
|
|
return int(round(f * 3.0));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// bake lighting function
|
|
//-----------------------------------------------------------------------------
|
|
|
|
float3 GetBakedDiffuseLigthing(SurfaceData surfaceData, BuiltinData builtinData)
|
|
{
|
|
float3 diffuseColor;
|
|
|
|
if (surfaceData.materialId == MATERIALID_LIT_STANDARD)
|
|
{
|
|
diffuseColor = surfaceData.baseColor * (1.0 - surfaceData.metalic);
|
|
}
|
|
else if (surfaceData.materialId == MATERIALID_LIT_SSS)
|
|
{
|
|
diffuseColor = surfaceData.baseColor;
|
|
}
|
|
else if (surfaceData.materialId == MATERIALID_LIT_CLEAR_COAT)
|
|
{
|
|
diffuseColor = surfaceData.baseColor * (1.0 - surfaceData.metalic);
|
|
}
|
|
else if (surfaceData.materialId == MATERIALID_LIT_SPECULAR)
|
|
{
|
|
diffuseColor = surfaceData.baseColor;
|
|
}
|
|
|
|
return builtinData.bakeDiffuseLighting * surfaceData.ambientOcclusion * diffuseColor + builtinData.emissiveColor * builtinData.emissiveIntensity;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// conversion function for deferred
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#define GBUFFER_MATERIAL_COUNT 3
|
|
|
|
// Encode SurfaceData (BSDF parameters) into GBuffer
|
|
// Must be in sync with RT declared in HDRenderLoop.cs ::Rebuild
|
|
void EncodeIntoGBuffer( SurfaceData surfaceData,
|
|
out float4 outGBuffer0,
|
|
out float4 outGBuffer1,
|
|
out float4 outGBuffer2)
|
|
{
|
|
// RT0 - 8:8:8:8 sRGB
|
|
outGBuffer0 = float4(surfaceData.baseColor, surfaceData.specularOcclusion);
|
|
|
|
// RT1 - 10:10:10:2
|
|
// Encode normal on 20bit with oct compression
|
|
float2 octNormalWS = PackNormalOctEncode(surfaceData.normalWS);
|
|
// We store perceptualRoughness instead of roughness because it save a sqrt ALU when decoding
|
|
// (as we want both perceptualRoughness and roughness for the lighting due to Disney Diffuse model)
|
|
// TODO: Store 2 bit of flag into perceptualSmoothness (one for SSR, other is free (deferred planar reflection ID ? / MatID extension ?)
|
|
outGBuffer1 = float4(octNormalWS * 0.5 + 0.5, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness), PackMaterialId(surfaceData.materialId));
|
|
|
|
// RT2 - 8:8:8:8
|
|
if (surfaceData.materialId == MATERIALID_LIT_STANDARD)
|
|
{
|
|
// Encode tangent on 16bit with oct compression
|
|
float2 octTangentWS = PackNormalOctEncode(surfaceData.tangentWS);
|
|
// TODO: store metal and specular together, specular should be an enum (fixed value)
|
|
outGBuffer2 = float4(octTangentWS * 0.5 + 0.5, surfaceData.anisotropy, surfaceData.metalic);
|
|
}
|
|
else if (surfaceData.materialId == MATERIALID_LIT_SSS)
|
|
{
|
|
outGBuffer2 = float4(surfaceData.subSurfaceRadius, surfaceData.thickness, 0.0, surfaceData.subSurfaceProfile / 8.0f); // Number of profile not define yet
|
|
}
|
|
else if (surfaceData.materialId == MATERIALID_LIT_CLEAR_COAT)
|
|
{
|
|
// Encode coat normal on 16bit with oct compression
|
|
float2 octCoatNormalWS = PackNormalOctEncode(surfaceData.coatNormalWS);
|
|
// TODO: store metal and specular together, specular should be an enum (fixed value)
|
|
outGBuffer2 = float4(octCoatNormalWS * 0.5 + 0.5, PerceptualSmoothnessToRoughness(surfaceData.coatPerceptualSmoothness), surfaceData.metalic);
|
|
}
|
|
else if (surfaceData.materialId == MATERIALID_LIT_SPECULAR)
|
|
{
|
|
outGBuffer2 = float4(surfaceData.specularColor, 0.0);
|
|
}
|
|
}
|
|
|
|
BSDFData DecodeFromGBuffer( float4 inGBuffer0,
|
|
float4 inGBuffer1,
|
|
float4 inGBuffer2)
|
|
{
|
|
BSDFData bsdfData = (BSDFData)0;
|
|
|
|
float3 baseColor = inGBuffer0.rgb;
|
|
bsdfData.specularOcclusion = inGBuffer0.a;
|
|
|
|
bsdfData.normalWS = UnpackNormalOctEncode(float2(inGBuffer1.r * 2.0 - 1.0, inGBuffer1.g * 2.0 - 1.0));
|
|
bsdfData.perceptualRoughness = inGBuffer1.b;
|
|
bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
|
|
bsdfData.materialId = UnpackMaterialId(inGBuffer1.a);
|
|
|
|
if (bsdfData.materialId == MATERIALID_LIT_STANDARD)
|
|
{
|
|
float metalic = inGBuffer2.a;
|
|
// TODO extract spec
|
|
float specular = 0.04;
|
|
float anisotropy = inGBuffer2.b;
|
|
|
|
bsdfData.diffuseColor = baseColor * (1.0 - metalic);
|
|
bsdfData.fresnel0 = lerp(float3(specular, specular, specular), baseColor, metalic);
|
|
|
|
bsdfData.tangentWS = UnpackNormalOctEncode(float2(inGBuffer2.rg * 2.0 - 1.0));
|
|
bsdfData.bitangentWS = cross(bsdfData.normalWS, bsdfData.tangentWS);
|
|
ConvertAnisotropyToRoughness(bsdfData.roughness, anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
|
|
}
|
|
else if (bsdfData.materialId == MATERIALID_LIT_SSS)
|
|
{
|
|
bsdfData.diffuseColor = baseColor;
|
|
bsdfData.fresnel0 = 0.028; // TODO take from subSurfaceProfile
|
|
bsdfData.subSurfaceRadius = inGBuffer2.r;
|
|
bsdfData.thickness = inGBuffer2.g;
|
|
bsdfData.subSurfaceProfile = inGBuffer2.a * 8.0f;
|
|
}
|
|
else if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT)
|
|
{
|
|
float metalic = inGBuffer2.a;
|
|
// TODO extract spec
|
|
float specular = 0.04;
|
|
|
|
bsdfData.diffuseColor = baseColor * (1.0 - metalic);
|
|
bsdfData.fresnel0 = lerp(float3(specular, specular, specular), baseColor, metalic);
|
|
bsdfData.coatNormalWS = UnpackNormalOctEncode(float2(inGBuffer2.rg * 2.0 - 1.0));
|
|
bsdfData.coatRoughness = inGBuffer2.b;
|
|
}
|
|
else if (bsdfData.materialId == MATERIALID_LIT_SPECULAR)
|
|
{
|
|
bsdfData.diffuseColor = baseColor;
|
|
bsdfData.fresnel0 = inGBuffer2.rgb;
|
|
}
|
|
|
|
return bsdfData;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Debug method (use to display values)
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void GetSurfaceDataDebug(uint paramId, SurfaceData surfaceData, inout float3 result, inout bool needLinearToSRGB)
|
|
{
|
|
switch (paramId)
|
|
{
|
|
case DEBUGVIEW_LIT_SURFACEDATA_BASE_COLOR:
|
|
result = surfaceData.baseColor; needLinearToSRGB = true;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_OCCLUSION:
|
|
result = surfaceData.specularOcclusion.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_NORMAL_WS:
|
|
result = surfaceData.normalWS * 0.5 + 0.5;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_PERCEPTUAL_SMOOTHNESS:
|
|
result = surfaceData.perceptualSmoothness.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_MATERIAL_ID:
|
|
result = GetIndexColor(surfaceData.materialId);
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_AMBIENT_OCCLUSION:
|
|
result = surfaceData.ambientOcclusion.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_TANGENT_WS:
|
|
result = surfaceData.tangentWS * 0.5 + 0.5;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_ANISOTROPY:
|
|
result = surfaceData.anisotropy.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_METALIC:
|
|
result = surfaceData.metalic.xxx;
|
|
break;
|
|
// TODO: Remap here!
|
|
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR:
|
|
result = surfaceData.specular.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_SUB_SURFACE_RADIUS:
|
|
result = surfaceData.subSurfaceRadius.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_THICKNESS:
|
|
result = surfaceData.thickness.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_SUB_SURFACE_PROFILE:
|
|
result = GetIndexColor(surfaceData.subSurfaceProfile);
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_COAT_NORMAL_WS:
|
|
result = surfaceData.coatNormalWS * 0.5 + 0.5;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_COAT_PERCEPTUAL_SMOOTHNESS:
|
|
result = surfaceData.coatPerceptualSmoothness.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_COLOR:
|
|
result = surfaceData.specularColor; needLinearToSRGB = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GetBSDFDataDebug(uint paramId, BSDFData bsdfData, inout float3 result, inout bool needLinearToSRGB)
|
|
{
|
|
switch (paramId)
|
|
{
|
|
case DEBUGVIEW_LIT_BSDFDATA_DIFFUSE_COLOR:
|
|
result = bsdfData.diffuseColor; needLinearToSRGB = true;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_FRESNEL0:
|
|
result = bsdfData.fresnel0;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_SPECULAR_OCCLUSION:
|
|
result = bsdfData.specularOcclusion.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_NORMAL_WS:
|
|
result = bsdfData.normalWS * 0.5 + 0.5;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_PERCEPTUAL_ROUGHNESS:
|
|
result = bsdfData.perceptualRoughness.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS:
|
|
result = bsdfData.roughness.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_MATERIAL_ID:
|
|
result = GetIndexColor(bsdfData.materialId);
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_TANGENT_WS:
|
|
result = bsdfData.tangentWS * 0.5 + 0.5;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_BITANGENT_WS:
|
|
result = bsdfData.bitangentWS * 0.5 + 0.5;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_T:
|
|
result = bsdfData.roughnessT.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_ROUGHNESS_B:
|
|
result = bsdfData.roughnessB.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_SUB_SURFACE_RADIUS:
|
|
result = bsdfData.subSurfaceRadius.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_THICKNESS:
|
|
result = bsdfData.thickness.xxx;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_SUB_SURFACE_PROFILE:
|
|
result = GetIndexColor(bsdfData.subSurfaceProfile);
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_COAT_NORMAL_WS:
|
|
result = bsdfData.coatNormalWS * 0.5 + 0.5;
|
|
break;
|
|
case DEBUGVIEW_LIT_BSDFDATA_COAT_ROUGHNESS:
|
|
result = bsdfData.coatRoughness.xxx;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// EvaluateBSDF functions for each light type
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void EvaluateBSDF_Punctual( float3 V, float3 positionWS, PunctualLightData lightData, BSDFData bsdfData,
|
|
out float4 diffuseLighting,
|
|
out float4 specularLighting)
|
|
{
|
|
// All punctual light type in the same formula, attenuation is neutral depends on light type.
|
|
// light.positionWS is the normalize light direction in case of directional light and invSqrAttenuationRadius is 0
|
|
// mean dot(unL, unL) = 1 and mean GetDistanceAttenuation() will return 1
|
|
// For point light and directional GetAngleAttenuation() return 1
|
|
|
|
float3 unL = lightData.positionWS - positionWS * lightData.useDistanceAttenuation;
|
|
float3 L = normalize(unL);
|
|
|
|
float attenuation = GetDistanceAttenuation(unL, lightData.invSqrAttenuationRadius);
|
|
attenuation *= GetAngleAttenuation(L, lightData.forward, lightData.angleScale, lightData.angleOffset);
|
|
float illuminance = saturate(dot(bsdfData.normalWS, L)) * attenuation;
|
|
|
|
diffuseLighting = float4(0.0, 0.0, 0.0, 1.0);
|
|
specularLighting = float4(0.0, 0.0, 0.0, 1.0);
|
|
|
|
if (illuminance > 0.0f)
|
|
{
|
|
float NdotV = abs(dot(bsdfData.normalWS, V)) + 1e-5f; // TODO: check Eric idea about doing that when writting into the GBuffer (with our forward decal)
|
|
float3 H = normalize(V + L);
|
|
float LdotH = saturate(dot(L, H));
|
|
float NdotH = saturate(dot(bsdfData.normalWS, H));
|
|
float NdotL = saturate(dot(bsdfData.normalWS, L));
|
|
float3 F = F_Schlick(bsdfData.fresnel0, LdotH);
|
|
float Vis = V_SmithJointGGX(NdotL, NdotV, bsdfData.roughness);
|
|
float D = D_GGXDividePI(NdotH, bsdfData.roughness);
|
|
specularLighting.rgb = F * Vis * D;
|
|
#ifdef DIFFUSE_LAMBERT_BRDF
|
|
float diffuseTerm = LambertDividePI();
|
|
#else
|
|
float diffuseTerm = DisneyDiffuseDividePI(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
|
|
#endif
|
|
diffuseLighting.rgb = bsdfData.diffuseColor * diffuseTerm;
|
|
|
|
diffuseLighting.rgb *= lightData.color * illuminance;
|
|
specularLighting.rgb *= lightData.color * illuminance;
|
|
}
|
|
}
|
|
|
|
#endif // UNITY_MATERIAL_LIT_INCLUDED
|