浏览代码

Added iridescence on the bottom of the stack (needs a bit of work still, had to hack to avoid TIR, dual normal will still cause artefacts because of the fake refraction through the geometric normal. Also to check/fix f0 handling and conversion).

/main
Stephane Laroche 6 年前
当前提交
6830f5c5
共有 8 个文件被更改,包括 154 次插入27 次删除
  1. 16
      com.unity.render-pipelines.core/CoreRP/ShaderLibrary/BSDF.hlsl
  2. 12
      com.unity.render-pipelines.high-definition/HDRP/Editor/Material/StackLit/StackLitUI.cs
  3. 3
      com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.cs
  4. 34
      com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.cs.hlsl
  5. 65
      com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.hlsl
  6. 33
      com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.shader
  7. 5
      com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLitData.hlsl
  8. 13
      com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLitProperties.hlsl

16
com.unity.render-pipelines.core/CoreRP/ShaderLibrary/BSDF.hlsl


}
// Evaluate the reflectance for a thin-film layer on top of a dielectric medum.
real3 EvalIridescence(real eta_1, real cosTheta1, real iridescenceThickness, real3 baseLayerFresnel0)
real3 EvalIridescence(real eta_1, real cosTheta1, real iridescenceThickness, real3 baseLayerFresnel0, real iorOverBaseLayer = 0.0)
{
// iridescenceThickness unit is micrometer for this equation here. Mean 0.5 is 500nm.
real Dinc = 3.0 * iridescenceThickness;

// Force eta_2 -> eta_1 when Dinc -> 0.0
// real eta_2 = lerp(eta_1, eta_2, smoothstep(0.0, 0.03, Dinc));
// Evaluate the cosTheta on the base layer (Snell law)
real cosTheta2 = sqrt(1.0 - Sq(eta_1 / eta_2) * (1.0 - Sq(cosTheta1)));
real sinTheta2 = Sq(eta_1 / eta_2) * (1.0 - Sq(cosTheta1));
//debug: TIR if( sinTheta2 > 1.0 ) return real3(1.0, 0.0, 0.0);
real cosTheta2 = sqrt(1.0 - sinTheta2);
// First interface
real R0 = IorToFresnel0(eta_2, eta_1);

real phi21 = PI - phi12;
// Second interface
// The f0 or the base should account for the new computed eta_2 on top.
// This is optionally done if we are given the needed current ior over the base layer that is accounted for
// in the baseLayerFresnel0 parameter:
if(iorOverBaseLayer > 0.0)
{
// Fresnel0ToIor will give us a ratio of baseIor/topIor, hence we * iorOverBaseLayer to get the baseIor
real3 baseIor = iorOverBaseLayer * Fresnel0ToIor(baseLayerFresnel0 + 0.0001); // guard against 1.0
baseLayerFresnel0 = IorToFresnel0(baseIor, eta_2);
}
real3 R23 = F_Schlick(baseLayerFresnel0, cosTheta2);
real phi23 = 0.0;

12
com.unity.render-pipelines.high-definition/HDRP/Editor/Material/StackLit/StackLitUI.cs


protected const string k_IridescenceThickness = "_IridescenceThickness";
protected const string k_IridescenceThicknessMap = "_IridescenceThicknessMap";
protected const string k_IridescenceThicknessMapUV = "_IridescenceThicknessMapUV";
protected const string k_IridescenceMask = "_IridescenceMask";
protected const string k_IridescenceMaskMap = "_IridescenceMaskMap";
protected const string k_IridescenceMaskMapUV = "_IridescenceMaskMapUV";
// Stencil is use to control lighting mode (regular, split lighting)
protected const string kStencilRef = "_StencilRef";

new GroupProperty(this, "_Iridescence", "Iridescence", new BaseProperty[]
{
new Property(this, "_IridescenceIor", "IOR", "Index of refraction of iridescence layer", false),
new Property(this, "_IridescenceThickness", "Thickness", "Iridescence thickness (Remap to 0..3000nm)", false),
//just to test: to use the same EvalIridescence as lit, find a good mapping for the top IOR (over the iridescence dielectric film)
//when having iridescence:
//new Property(this, "_IridescenceIor", "TopIOR", "Index of refraction on top of iridescence layer", false),
new TextureProperty(this, k_IridescenceMaskMap, k_IridescenceMask, "Iridescence Mask", "Iridescence Mask", false),
new TextureProperty(this, k_IridescenceThicknessMap, k_IridescenceThickness, "Iridescence thickness (Remap to 0..3000nm)", "Iridescence thickness (Remap to 0..3000nm)", false),
}, _ => EnableIridescence.BoolValue == true),
new GroupProperty(this, "_SSS", "Sub-Surface Scattering", new BaseProperty[]

SetupTextureMaterialProperty(material, k_Thickness);
SetupTextureMaterialProperty(material, k_Anisotropy);
SetupTextureMaterialProperty(material, k_IridescenceThickness);
SetupTextureMaterialProperty(material, k_IridescenceMask);
SetupTextureMaterialProperty(material, k_CoatSmoothness);
// Check if we are using specific UVs.

(TextureProperty.UVMapping)material.GetFloat(k_ThicknessMapUV),
(TextureProperty.UVMapping)material.GetFloat(k_AnisotropyMapUV),
(TextureProperty.UVMapping)material.GetFloat(k_IridescenceThicknessMapUV),
(TextureProperty.UVMapping)material.GetFloat(k_IridescenceMaskMapUV),
(TextureProperty.UVMapping)material.GetFloat(k_CoatSmoothnessMapUV),
(TextureProperty.UVMapping)material.GetFloat(k_CoatNormalMapUV),
};

3
com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.cs


public float iridescenceIor;
[SurfaceDataAttributes("IridescenceThickness")]
public float iridescenceThickness;
[SurfaceDataAttributes("Iridescence Mask")]
public float iridescenceMask;
// Top interface and media (clearcoat)
[SurfaceDataAttributes("Coat Smoothness")]

// iridescence
public float iridescenceIor;
public float iridescenceThickness;
public float iridescenceMask;
// SSS
public uint diffusionProfile;

34
com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.cs.hlsl


#define DEBUGVIEW_STACKLIT_SURFACEDATA_ANISOTROPY (1315)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_IRIDESCENCE_IOR (1316)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_IRIDESCENCE_THICKNESS (1317)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_SMOOTHNESS (1318)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_IOR (1319)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_THICKNESS (1320)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_EXTINCTION_COEFFICIENT (1321)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_DIFFUSION_PROFILE (1322)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_SUBSURFACE_MASK (1323)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_THICKNESS (1324)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_IRIDESCENCE_MASK (1318)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_SMOOTHNESS (1319)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_IOR (1320)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_THICKNESS (1321)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_EXTINCTION_COEFFICIENT (1322)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_DIFFUSION_PROFILE (1323)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_SUBSURFACE_MASK (1324)
#define DEBUGVIEW_STACKLIT_SURFACEDATA_THICKNESS (1325)
//
// UnityEngine.Experimental.Rendering.HDPipeline.StackLit+BSDFData: static fields

#define DEBUGVIEW_STACKLIT_BSDFDATA_COAT_EXTINCTION (1424)
#define DEBUGVIEW_STACKLIT_BSDFDATA_IRIDESCENCE_IOR (1425)
#define DEBUGVIEW_STACKLIT_BSDFDATA_IRIDESCENCE_THICKNESS (1426)
#define DEBUGVIEW_STACKLIT_BSDFDATA_DIFFUSION_PROFILE (1427)
#define DEBUGVIEW_STACKLIT_BSDFDATA_SUBSURFACE_MASK (1428)
#define DEBUGVIEW_STACKLIT_BSDFDATA_THICKNESS (1429)
#define DEBUGVIEW_STACKLIT_BSDFDATA_USE_THICK_OBJECT_MODE (1430)
#define DEBUGVIEW_STACKLIT_BSDFDATA_TRANSMITTANCE (1431)
#define DEBUGVIEW_STACKLIT_BSDFDATA_IRIDESCENCE_MASK (1427)
#define DEBUGVIEW_STACKLIT_BSDFDATA_DIFFUSION_PROFILE (1428)
#define DEBUGVIEW_STACKLIT_BSDFDATA_SUBSURFACE_MASK (1429)
#define DEBUGVIEW_STACKLIT_BSDFDATA_THICKNESS (1430)
#define DEBUGVIEW_STACKLIT_BSDFDATA_USE_THICK_OBJECT_MODE (1431)
#define DEBUGVIEW_STACKLIT_BSDFDATA_TRANSMITTANCE (1432)
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.StackLit+SurfaceData
// PackingRules = Exact

float anisotropy;
float iridescenceIor;
float iridescenceThickness;
float iridescenceMask;
float coatPerceptualSmoothness;
float coatIor;
float coatThickness;

float3 coatExtinction;
float iridescenceIor;
float iridescenceThickness;
float iridescenceMask;
uint diffusionProfile;
float subsurfaceMask;
float thickness;

break;
case DEBUGVIEW_STACKLIT_SURFACEDATA_IRIDESCENCE_THICKNESS:
result = surfacedata.iridescenceThickness.xxx;
break;
case DEBUGVIEW_STACKLIT_SURFACEDATA_IRIDESCENCE_MASK:
result = surfacedata.iridescenceMask.xxx;
break;
case DEBUGVIEW_STACKLIT_SURFACEDATA_COAT_SMOOTHNESS:
result = surfacedata.coatPerceptualSmoothness.xxx;

break;
case DEBUGVIEW_STACKLIT_BSDFDATA_IRIDESCENCE_THICKNESS:
result = bsdfdata.iridescenceThickness.xxx;
break;
case DEBUGVIEW_STACKLIT_BSDFDATA_IRIDESCENCE_MASK:
result = bsdfdata.iridescenceMask.xxx;
break;
case DEBUGVIEW_STACKLIT_BSDFDATA_DIFFUSION_PROFILE:
result = GetIndexColor(bsdfdata.diffusionProfile);

65
com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.hlsl


#else // ! _MATERIAL_FEATURE_COAT
// For iridescence, we will reuse the recompute per light keyword even when not vlayered.
// When vlayered and iridescence is on, iridescence is also automatically recomputed per light too,
// so the following gives the recompute option for iridescence when NOT vlayered:
#ifdef VLAYERED_RECOMPUTE_PERLIGHT
# if _MATERIAL_FEATURE_IRIDESCENCE
# define IRIDESCENCE_RECOMPUTE_PERLIGHT
# endif
#endif
# undef VLAYERED_RECOMPUTE_PERLIGHT
# undef VLAYERED_USE_REFRACTED_ANGLES_FOR_BASE
# undef _MATERIAL_FEATURE_COAT_NORMALMAP // enforce a "coat enabled subfeature" condition on this shader_feature

bsdfData.bitangentWS = bitangentWS;
}
void FillMaterialIridescence(float mask, float thickness, float ior, inout BSDFData bsdfData)
{
bsdfData.iridescenceMask = mask;
bsdfData.iridescenceThickness = thickness;
bsdfData.iridescenceIor = ior;
}
void FillMaterialCoatData(float coatPerceptualRoughness, float coatIor, float coatThickness, float3 coatExtinction, inout BSDFData bsdfData)
{
bsdfData.coatPerceptualRoughness = coatPerceptualRoughness;

FillMaterialAnisotropy(surfaceData.anisotropy, surfaceData.tangentWS, cross(surfaceData.normalWS, surfaceData.tangentWS), bsdfData);
}
if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_IRIDESCENCE))
{
FillMaterialIridescence(surfaceData.iridescenceMask, surfaceData.iridescenceThickness, surfaceData.iridescenceIor, bsdfData);
}
if (HasFeatureFlag(surfaceData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_COAT))
{
FillMaterialCoatData(PerceptualSmoothnessToPerceptualRoughness(surfaceData.coatPerceptualSmoothness),

// for it (hence the name iblF in Lit). Here, we will fold all data into
// lobe-indexed arrays.
// For iridescence, to avoid recalculation per analytical light, we store the calculated
// iridescence reflectance that was used (as an approximation to "iridescent pre-integrated" FGD)
// to calculate FGD with the precalculated table:
float3 fresnelIridforCalculatingFGD;
// For clarity, we will dump the base layer lobes roughnesses used by analytical lights
// here, to avoid confusion with the per-vlayer (vs per lobe) vLayerPerceptualRoughness

// Update energy
R12 = F_Schlick(bsdfData.fresnel0, ctiForFGD);
if (HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_IRIDESCENCE))
{
if (bsdfData.iridescenceMask > 0.0)
{
//float topIor = bsdfData.coatIor;
// TODO:
// We will avoid using coatIor directly as with the fake refraction, it can cause TIR
// which even when handled in EvalIridescence (tested), doesn't look pleasing and
// creates a discontinuity.
float scale = clamp((1.0-bsdfData.coatPerceptualRoughness), 0.0, 1.0);
float topIor = lerp(1.0001, bsdfData.coatIor, scale);
R12 = lerp(R12, EvalIridescence(topIor, ctiForFGD, bsdfData.iridescenceThickness, bsdfData.fresnel0), bsdfData.iridescenceMask);
}
}
T12 = 0.0;
#ifdef VLAYERED_DIFFUSE_ENERGY_HACKED_TERM
// Still should use FGD!

iblN[0] = iblN[1] = N[0];
} // ...no anisotropy
float3 f0forCalculatingFGD = bsdfData.fresnel0;
if (HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_IRIDESCENCE))
{
float topIor = 1.0; // Air on top, no coat.
if (bsdfData.iridescenceMask > 0.0)
{
preLightData.fresnelIridforCalculatingFGD = EvalIridescence(topIor, NdotV[0], bsdfData.iridescenceThickness, bsdfData.fresnel0);
f0forCalculatingFGD = lerp(bsdfData.fresnel0, preLightData.fresnelIridforCalculatingFGD, bsdfData.iridescenceMask);
}
}
// IBL
// Handle IBL pre calculated data + GGX multiscattering energy loss compensation term

bsdfData.fresnel0,
f0forCalculatingFGD,
preLightData.specularFGD[BASE_LOBEA_IDX],
diffuseFGD[0],
specularReflectivity[BASE_LOBEA_IDX]);

bsdfData.fresnel0,
f0forCalculatingFGD,
preLightData.specularFGD[BASE_LOBEB_IDX],
diffuseFGD[1],
specularReflectivity[BASE_LOBEB_IDX]);

// --------------------------------------------------------------------
// TODO: Proper Fresnel
float3 F = F_Schlick(bsdfData.fresnel0, savedLdotH);
if (HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_IRIDESCENCE))
{
float3 fresnelIridescent = preLightData.fresnelIridforCalculatingFGD;
#ifdef IRIDESCENCE_RECOMPUTE_PERLIGHT
float topIor = 1.0; // default air on top.
fresnelIridescent = EvalIridescence(topIor, savedLdotH, bsdfData.iridescenceThickness, bsdfData.fresnel0);
#endif
F = lerp(F, fresnelIridescent, bsdfData.iridescenceMask);
}
if (HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_ANISOTROPY))
{

33
com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.shader


[HideInInspector] _ThicknessRange("Thickness Range", Vector) = (0, 1, 0, 0)
[ToggleUI] _EnableIridescence("Enable Iridescence", Float) = 0.0 // UI only
_IridescenceIor("Coat IOR", Range(1.0, 2.0)) = 1.5
_IridescenceThickness("_IridescenceThickness", Range(0.0, 1.0)) = 0.0
_IridescenceThicknessMap("IridescenceThickness Color Map", 2D) = "black" {}
_IridescenceIor("TopIOR over iridescent layer", Range(1.0, 2.0)) = 1.5
[HideInInspector] _IridescenceThicknessMapShow("IridescenceThickness Map Show", Float) = 0
_IridescenceThickness("IridescenceThickness", Range(0.0, 1.0)) = 0.0
_IridescenceThicknessMap("IridescenceThickness Map", 2D) = "black" {}
_IridescenceThicknessMapChannel("IridescenceThickness Mask Map Channel", Float) = 0.0
_IridescenceThicknessMapChannelMask("IridescenceThickness Mask Map Channel Mask", Vector) = (1, 0, 0, 0)
_IridescenceThicknessMapChannel("IridescenceThickness Map Channel", Float) = 0.0
_IridescenceThicknessMapChannelMask("IridescenceThickness Map Channel Mask", Vector) = (1, 0, 0, 0)
_IridescenceThicknessRemap("IridescenceThickness Remap", Vector) = (0, 1, 0, 0)
[ToggleUI] _IridescenceThicknessRemapInverted("Invert IridescenceThickness Remap", Float) = 0.0
[HideInInspector] _IridescenceMaskMapShow("Iridescence Mask Map Show", Float) = 0
_IridescenceMask("Iridescence Mask", Range(0.0, 1.0)) = 1.0
_IridescenceMaskMap("Iridescence Mask Map", 2D) = "black" {}
_IridescenceMaskUseMap("Iridescence Mask Use Map", Float) = 0
_IridescenceMaskMapUV("Iridescence Mask Map UV", Float) = 0.0
_IridescenceMaskMapUVLocal("Iridescence Mask UV Local", Float) = 0.0
_IridescenceMaskMapChannel("Iridescence Mask Map Channel", Float) = 0.0
_IridescenceMaskMapChannelMask("Iridescence Mask Map Channel Mask", Vector) = (1, 0, 0, 0)
_IridescenceMaskRemap("Iridescence Mask Remap", Vector) = (0, 1, 0, 0)
[HideInInspector] _IridescenceMaskRange("Iridescence Mask Range", Vector) = (0, 1, 0, 0)
_DistortionVectorMap("DistortionVectorMap", 2D) = "black" {}
[ToggleUI] _DistortionEnable("Enable Distortion", Float) = 0.0

#pragma multi_compile _ DEBUG_DISPLAY
//NEWLITTODO
//#pragma multi_compile _ LIGHTMAP_ON
//#pragma multi_compile _ DIRLIGHTMAP_COMBINED
//#pragma multi_compile _ DYNAMICLIGHTMAP_ON
//#pragma multi_compile _ SHADOWS_SHADOWMASK
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
#pragma multi_compile _ DYNAMICLIGHTMAP_ON
#pragma multi_compile _ SHADOWS_SHADOWMASK
// #include "../../Lighting/Forward.hlsl" : nothing left in there.
//#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS

5
com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLitData.hlsl


surfaceData.iridescenceThickness = dot(SAMPLE_TEXTURE2D_SCALE_BIAS(_IridescenceThicknessMap), _IridescenceThicknessMapChannelMask);
surfaceData.iridescenceThickness = lerp(_IridescenceThicknessRange.x, _IridescenceThicknessRange.y, surfaceData.iridescenceThickness);
surfaceData.iridescenceThickness = lerp(_IridescenceThickness, surfaceData.iridescenceThickness, _IridescenceThicknessUseMap);
surfaceData.iridescenceMask = dot(SAMPLE_TEXTURE2D_SCALE_BIAS(_IridescenceMaskMap), _IridescenceMaskMapChannelMask);
surfaceData.iridescenceMask = lerp(_IridescenceMaskRange.x, _IridescenceMaskRange.y, surfaceData.iridescenceMask);
surfaceData.iridescenceMask = lerp(_IridescenceMask, surfaceData.iridescenceMask, _IridescenceMaskUseMap);
surfaceData.iridescenceMask = 0.0;
#endif
#if defined(_MATERIAL_FEATURE_SUBSURFACE_SCATTERING) || defined(_MATERIAL_FEATURE_TRANSMISSION)

13
com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLitProperties.hlsl


TEXTURE2D(_IridescenceThicknessMap);
SAMPLER(sampler_IridescenceThicknessMap);
TEXTURE2D(_IridescenceMaskMap);
SAMPLER(sampler_IridescenceMaskMap);
TEXTURE2D(_SubsurfaceMaskMap);
SAMPLER(sampler_SubsurfaceMaskMap);

float4 _IridescenceThicknessMapChannelMask;
float4 _IridescenceThicknessRange;
float _IridescenceIor;
float _IridescenceMask;
float _IridescenceMaskUseMap;
float _IridescenceMaskMapUV;
float _IridescenceMaskMapUVLocal;
float4 _IridescenceMaskMap_ST;
float4 _IridescenceMaskMap_TexelSize;
float4 _IridescenceMaskMap_MipInfo;
float4 _IridescenceMaskMapChannelMask;
float4 _IridescenceMaskRange;
int _DiffusionProfile;
float _SubsurfaceMask;

正在加载...
取消
保存