XDRender_ObjPass_ShaderMode_Cloth(2) 布料渲染模型 绒

XDRender_ObjPass_ShaderMode_Cloth(2) 布料渲染模型 绒

image-20201111202248360

​ 灯芯绒

image-20201115213047000

前言


正文


绒: 稀疏,交错

-----------------在掠射角处产生镜面高光

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

现实环境

灯芯绒

灯芯绒组织采用两组纬纱与一组经纱交织的纬二重组织,地组织有平纹斜纹等。灯芯绒由一组经纱和二组纬纱织成,其中一组纬纱(称地纬)与经纱交织成固结绒毛的地布,另一组纬纱(称绒纬)与经纱交织构成有规律的浮纬,割断后形成绒毛。

灯芯绒采用纬二重组织织制、再经割绒整理,布面呈灯芯状绒条的织物,又称条绒

现实环境下的灯芯绒

image-20201115201422408

image-20201115201437241

下面是UNREAL的

image-20201115204754315

天鹅绒

天鹅绒使用桑蚕丝作原料也可用桑蚕丝作经,棉纱作纬交织的地组织上,以桑蚕丝或人造丝起绒圈。织造时每织四根绒线后织入一根起绒杆(细铁丝),织到一定长度时(约20厘米左右),即在机上用割刀沿铁丝剖割,铁丝脱离织物,则成毛绒。此毛绒根据纹样的设计,就能使纹样清晰地显示在缎面上,并有光泽。构成织物的纹样有两种形式,一种是绒花缎地,即漳缎;一种是绒地缎花,即天鹅绒。

image-20201115201836495

image-20201115201909097

总结


备注

人生当苦,笑着看看
原文地址:https://www.cnblogs.com/BaiPao-XD/p/13967231.html