XDRender_ObjPass_ShaderMode_Cloth(2) 布料渲染模型 绒
灯芯绒
前言
正文
绒: 稀疏,交错
-----------------在掠射角处产生镜面高光
Sheen-brdf
基于 Estevez 和 Kulla[Estevez2017]的 Sheen-brdf 闭包,是一个微表面 Sheen-brdf。它模拟了织物的外观,其中表面的面是圆柱形的“纤维”,其轴线平行于表面发现,在掠射角处产生镜面高光。从概念上讲,这位于基础底的顶部,因此传输到基础底层的能量被光泽反射降低
sheen_layer = sheen * sheen_color * sheen_brdf(...) + (1 - sheen * reflectance(sheen_brdf)) * base_mix
光泽 _ 层=光泽光泽 _ 颜色光泽 _brdf(…)+(1-光泽反射(光泽 _brdf))基础 _ 混合
其中基础混合闭包定义如下
Name 名称 | Type 类型 | Default 默认值 | Description 描述 | |
---|---|---|---|---|
sheen *光泽 |
float | 0.8 |
sheen_brdf 反射权重 |
|
sheen_color *光泽颜色 |
color | 1,1,1 |
sheen_brdf 反射颜色 |
|
sheen_roughness *光泽粗糙度 |
float | 0.3 |
sheen_brdf 反射粗糙度, 范围 [0,1] |
|
简化的模拟
第一种 gazing
这里可以参考Unity, 可以提前计算出掠射角的反射率,(半导体)
half oneMinusReflectivity = OneMinusReflectivityMetallic(metallic);
half reflectivity = 1.0 - oneMinusReflectivity;
outBRDFData.diffuse = albedo * oneMinusReflectivity;
outBRDFData.specular = lerp(kDieletricSpec.rgb, albedo, metallic);
#endif
outBRDFData.grazing = saturate(smoothness + reflectivity);
其中reflectivity:
0.04一个电解质最低的F0
#define kDieletricSpec half4(0.04, 0.04, 0.04, 1.0 - 0.04)
half OneMinusReflectivityMetallic(half metallic)
{
// We'll need oneMinusReflectivity, so
// 1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) = lerp(1-dielectricSpec, 0, metallic)
// store (1-dielectricSpec) in kDieletricSpec.a, then
// 1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) =
// = alpha - metallic * alpha
half oneMinusDielectricSpec = kDieletricSpec.a;
return oneMinusDielectricSpec - metallic * oneMinusDielectricSpec;
}
第二种 自定义实现
属性部分
1、我用CustomData的第一分量表示Cloth值(或者Sheen值), 第二个分量表示绒毛扩展度.
_CustomData("Cloth-SpecFabExtendScale", VECTOR) = (1, 0, 0, 1)
2、扩散,这一步还是按照上一节的实现. 并且用_SurfaceColor来存储.(由于绒毛我还不需要真实次表面, 就用Wrap来实现
_SurfaceColor("SurfaceColor", Color) = (0, 0, 0, 1)
实现部分
1、扩散的计算
float FabricScatterSale = saturate(pBRDF.surfacecolorScale);
float3 FuzzColor = pBRDF.surfacecolor * LightSurfaceWrap(context.NoL,FabricScatterSale);
float diffcuseTerm = Diffuse_Burley_Disney(pBRDF.perceptualRoughness,context.NoV,context.NoL,context.VoH);
float3 diffuseResult = pBRDF.diffuse * diffcuseTerm * lightColor * FuzzColor;//;
2、高光
这里先实现自己的,然后是UE的, DISN的
2.1.1 减弱FD的部分,这里直接利用NH来求F
inline float FabricD (float NdotH)
{
return 0.96 * pow(1 - NdotH, 2) + 0.057;
}
2.2.2 根据Rough来做区分
float NDF = D_GGX_Smis(pRoughness*pRoughness,pContext.NoH);
float G = GeometrySmith(pContext.NoV, pContext.NoL, pRoughness);
float VxD= pRoughness > 0.8 ? 1 * FabricD (pContext.NoH) : NDF * G;
2.2.3 更细碎的绒毛搞起
//--扩展细碎的绒毛
float3 specFabExtend = float3(1.0,1.0,1.0);//lerp(0.1,lightColor,pBRDF.roughness);
specFabExtend *= (context.NoL*0.5 + 0.5) * FabricScatterFresnelLerp(context.NoV, specFabExtendScale);
specFab += specFabExtend;
2.2.4 插值高光
插值值: 就是前面说到的CustomData.x, 这里也可以在内部多加一个. 但编辑器表现为Cloth
float clothValue = saturate(pBRDF.customData.x);
float specFabExtendScale = saturate(pBRDF.customData.y);
FDirectLightingResult DirectLightResult;
DirectLightResult.Diffuse = diffuseResult;
//--------------就是这里---------
DirectLightResult.Specular = lerp(specdefault,specFab,clothValue);
DirectLightResult.Transmission = 0;
第三种 迪斯尼
当然我们也可以按lum来做
//迪斯尼BRDF的扩散漫反射和高光
float3 Cdlin = mon2lin(baseColor);
float Cdlum = .3*Cdlin[0] + .6*Cdlin[1] + .1*Cdlin[2]; // luminance approx.
float3 Ctint = Cdlum > 0 ? Cdlin/Cdlum : float3(1,1,1); // normalize lum. to isolate hue+sat
float3 Cspec0 = lerp(_specular*.08*lerp(float3(1,1,1), Ctint, specularTint), Cdlin, metallic);
float3 Csheen = lerp(float3(1,1,1), Ctint, sheenTint);
// 漫反射多出的sheen
float3 Fsheen = FH * sheen * Csheen;
// 高光的F项
float3 Fs = lerp(Cspec0, float3(1,1,1), FH);
//最后的漫反射
((1/PI) * lerp(Fd, ss, subsurface)*Cdlin + Fsheen)* (1-metallic)
//高光
Gs*Fs*Ds
最后合成下
#if UEClothSpec
// Cloth - Asperity Scattering - Inverse Beckmann Layer
float3 specFab = FabricSpecularUnreal(pBRDF.specular,pBRDF.roughness,context)* lightColor;
#elif DisnyClothSpec
// Cloth - Asperity Scattering - Inverse Beckmann Layer
float3 specFab = FabricSpecularDisny(pBRDF.specular,pBRDF.roughness,context)* lightColor;
#else
//this is fab do extend
float3 specFab = FabricSpecularGGX(pBRDF.specular,pBRDF.roughness,context) * lightColor;
#endif
现实环境
灯芯绒
灯芯绒组织采用两组纬纱与一组经纱交织的纬二重组织,地组织有平纹、斜纹等。灯芯绒由一组经纱和二组纬纱织成,其中一组纬纱(称地纬)与经纱交织成固结绒毛的地布,另一组纬纱(称绒纬)与经纱交织构成有规律的浮纬,割断后形成绒毛。
灯芯绒采用纬二重组织织制、再经割绒整理,布面呈灯芯状绒条的织物,又称条绒
现实环境下的灯芯绒
下面是UNREAL的
天鹅绒
天鹅绒使用桑蚕丝作原料也可用桑蚕丝作经,棉纱作纬交织的地组织上,以桑蚕丝或人造丝起绒圈。织造时每织四根绒线后织入一根起绒杆(细铁丝),织到一定长度时(约20厘米左右),即在机上用割刀沿铁丝剖割,铁丝脱离织物,则成毛绒。此毛绒根据纹样的设计,就能使纹样清晰地显示在缎面上,并有光泽。构成织物的纹样有两种形式,一种是绒花缎地,即漳缎;一种是绒地缎花,即天鹅绒。