在网上找到的一些资源介绍了一些布料的光照模型(可以不看直接看后面的实现)

不同布料的光照模型

布料类型 推荐模型 原因说明 实现细节
丝绸 Cook-Torrance + Ashikhmin-Shirley各向异性 丝绸有强烈各向异性高光和虹彩效应 使用各向异性NDF,添加菲涅尔色彩变化
棉布 Oren-Nayar + 弱Cook-Torrance 棉布有微观纤维结构,微弱高光 粗糙度0.7-0.9,高光强度0.1-0.3
羊毛 Oren-Nayar + 次表面散射 羊毛完全哑光,强次表面散射 粗糙度>0.8,关闭高光,添加SSS
皮革 Cook-Torrance + 双层模型 皮革有清漆层和基底层的复合反射 双层粗糙度,清漆层高光
合成纤维 Cook-Torrance + Sheen 合成纤维有均匀高光和斜射光泽 中等粗糙度,添加Sheen项
牛仔布 Oren-Nayar + 法线细节 牛仔布粗糙,有编织纹理 高粗糙度,强法线贴图
天鹅绒 Cook-Torrance + 背向散射 天鹅绒顺光暗,逆光亮 特殊的背向散射模型

分析布料

布料表面分析 → 选择光照模型
├── 光滑有光泽 (粗糙度 < 0.4)
│   ├── 各向异性明显 → Cook-Torrance + 各向异性NDF
│   └── 各向同性 → Cook-Torrance (GGX)
├── 粗糙无光泽 (粗糙度 > 0.6)
│   ├── 有明显纤维结构 → Oren-Nayar
│   └── 均匀粗糙 → Lambert
└── 中等粗糙 (0.4 ≤ 粗糙度 ≤ 0.6)
    ├── 有微高光 → Cook-Torrance + Oren-Nayar混合
    └── 无高光 → Oren-Nayar

不同光照模型

PPT - 反射模型 PowerPoint演示文稿

 Lambert(朗伯)漫反射模型

// Lambert实现
float3 LambertDiffuse(float3 albedo, float3 normal, float3 lightDir)
{
    float NdotL = max(dot(normal, lightDir), 0.0);
    return albedo * NdotL;
}

// 适合:合成纤维、涤纶、光滑棉布
// 参数范围:粗糙度 > 0.7,无微观结构

 Oren-Nayar 模型

// Oren-Nayar实现
float OrenNayarDiffuse(float3 normal, float3 lightDir, float3 viewDir, float roughness)
{
    float sigma = roughness * PI / 2.0;  // 粗糙度转换为弧度
    float sigma2 = sigma * sigma;
    
    float A = 1.0 - 0.5 * sigma2 / (sigma2 + 0.33);
    float B = 0.45 * sigma2 / (sigma2 + 0.09);
    
    float NdotL = dot(normal, lightDir);
    float NdotV = dot(normal, viewDir);
    
    float theta_r = acos(NdotV);
    float theta_i = acos(NdotL);
    
    float alpha = max(theta_r, theta_i);
    float beta = min(theta_r, theta_i);
    
    // 计算方位角差
    float3 Lproj = normalize(lightDir - normal * NdotL);
    float3 Vproj = normalize(viewDir - normal * NdotV);
    float cosPhi = dot(Lproj, Vproj);
    
    float C = sin(alpha) * tan(beta);
    
    return max(0.0, NdotL) * (A + B * max(0.0, cosPhi) * C);
}

// 适合:棉布、羊毛、粗麻布、牛仔布
// 参数范围:粗糙度 0.5-1.0,有明显纤维结构

Cook-Torrance BRDF模型

// Cook-Torrance完整实现
float3 CookTorranceBRDF(float3 normal, float3 viewDir, float3 lightDir,
                       float roughness, float metallic, float3 F0)
{
    float3 halfVec = normalize(lightDir + viewDir);
    float NdotL = max(dot(normal, lightDir), 0.0);
    float NdotV = max(dot(normal, viewDir), 0.0);
    float NdotH = max(dot(normal, halfVec), 0.0);
    float VdotH = max(dot(viewDir, halfVec), 0.0);
    
    // 法线分布函数 (GGX/Trowbridge-Reitz)
    float a = roughness * roughness;
    float a2 = a * a;
    float NdotH2 = NdotH * NdotH;
    
    float denom = (NdotH2 * (a2 - 1.0) + 1.0);
    float D = a2 / (PI * denom * denom);
    
    // 几何遮蔽函数 (Smith-Schlick GGX)
    float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
    float G_l = NdotL / (NdotL * (1.0 - k) + k);
    float G_v = NdotV / (NdotV * (1.0 - k) + k);
    float G = G_l * G_v;
    
    // 菲涅尔项 (Schlick近似)
    float3 F = F0 + (1.0 - F0) * pow(1.0 - VdotH, 5.0);
    
    // 漫反射项 (能量守恒)
    float3 kD = (1.0 - F) * (1.0 - metallic);
    
    return (kD * albedo / PI + (D * F * G) / max(4.0 * NdotL * NdotV, 0.001));
}

// 适合:丝绸、皮革、合成纤维、有光泽的布料
// 参数范围:粗糙度 0.1-0.6,有明显高光反射

高光

布料类型 高光特征 视觉表现 物理原理
丝绸 强烈各向异性 方向性光泽,虹彩效应 纤维规则排列,薄膜干涉
棉布 微弱漫反射高光 柔和漫反射,几乎无镜面 不规则纤维散射
皮革 双层反射(清漆层) 表层光泽+基底漫反射 表面涂层+基底层
羊毛 无镜面高光 完全哑光,有绒毛光泽 纤维散射完全随机
天鹅绒 背向散射 逆光时发亮 纤维导向性反射
合成纤维 均匀高光+斜射光泽 均匀光泽,斜角有光晕 人造纤维规则结构

 丝绸 - 各向异性高光模型

物理原理

丝绸的高光来自纤维的规则排列,形成方向性镜面反射。由于纤维表面的薄膜干涉,还会产生虹彩效应。

// 丝绸完整高光模型
float3 SilkSpecular(float3 normal, float3 tangent, float3 bitangent,
                   float3 viewDir, float3 lightDir,
                   float roughnessU, float roughnessV,
                   float3 baseColor, float iridescence)
{
    // ========== 1. 各向异性NDF (Ward模型) ==========
    float3 halfVec = normalize(lightDir + viewDir);
    float NdotH = dot(normal, halfVec);
    float TdotH = dot(tangent, halfVec);
    float BdotH = dot(bitangent, halfVec);
    float NdotL = dot(normal, lightDir);
    float NdotV = dot(normal, viewDir);
    
    // Ward各向异性分布函数
    float exponent = (TdotH * TdotH) / (roughnessU * roughnessU) +
                     (BdotH * BdotH) / (roughnessV * roughnessV);
    exponent = exponent / (1.0 - NdotH * NdotH);
    
    float D = 1.0 / (4.0 * PI * roughnessU * roughnessV) *
              exp(-exponent) / sqrt(NdotL * NdotV);
    
    // ========== 2. 丝绸菲涅尔 (带色彩变化) ==========
    float3 F0 = float3(0.04, 0.04, 0.04);
    
    // 丝绸有更高的菲涅尔反射率
    F0 = lerp(F0, float3(0.08, 0.08, 0.08), 0.5);
    
    float LdotH = dot(lightDir, halfVec);
    float3 F = F0 + (1.0 - F0) * pow(1.0 - LdotH, 5.0);
    
    // 虹彩效应(薄膜干涉)
    if (iridescence > 0.0)
    {
        float3 iridescentColor = CalculateIridescence(viewDir, normal, 1.5);
        F = lerp(F, F * iridescentColor, iridescence);
    }
    
    // ========== 3. 丝绸特有的几何项 ==========
    // 丝绸表面更光滑,遮蔽较少
    float G = 1.0 / (LdotH * LdotH);
    
    // ========== 4. 最终高光 ==========
    float3 specular = (D * F * G) / (4.0 * NdotL * NdotV + 0.0001);
    
    // ========== 5. 二次高光(丝绸特有的微高光) ==========
    float secondarySpec = pow(NdotH, 50.0) * 0.1;
    specular += secondarySpec * F;
    
    return specular;
}

// 虹彩效应计算
float3 CalculateIridescence(float3 viewDir, float3 normal, float ior)
{
    float cosTheta = dot(viewDir, normal);
    float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
    
    // 薄膜干涉公式:光程差 = 2 * n * d * cosθ'
    // 简化:使用视角作为参数
    float angle = 1.0 - cosTheta;  // 掠射角
    
    // 不同波长的相位差
    float phaseR = angle * 100.0;
    float phaseG = angle * 120.0;
    float phaseB = angle * 140.0;
    
    // 干涉条纹
    float3 rainbow;
    rainbow.r = 0.5 + 0.5 * cos(phaseR);
    rainbow.g = 0.5 + 0.5 * cos(phaseG + 2.0 * PI / 3.0);
    rainbow.b = 0.5 + 0.5 * cos(phaseB + 4.0 * PI / 3.0);
    
    return rainbow;
}

棉布 - 微表面高光模型

物理原理

棉布的高光是漫反射主导的微弱高光,来自纤维表面的微表面散射

// 棉布高光模型(几乎无镜面,主要是漫反射)
float3 CottonSpecular(float3 normal, float3 viewDir, float3 lightDir,
                     float roughness, float3 albedo)
{
    // 棉布几乎没有镜面反射
    // 使用非常微弱的微表面散射高光
    
    float3 halfVec = normalize(lightDir + viewDir);
    float NdotH = dot(normal, halfVec);
    float NdotL = dot(normal, lightDir);
    float NdotV = dot(normal, viewDir);
    
    if (NdotL <= 0.0 || NdotV <= 0.0)
        return 0.0;
    
    // ========== 1. 棉布特有的微高光分布 ==========
    // 棉布高光非常宽泛模糊
    float alpha = roughness * roughness;
    
    // 使用更宽的分布(类似Beckmann但更模糊)
    float NdotH2 = NdotH * NdotH;
    float denom = NdotH2 * alpha + (1.0 - NdotH2);
    float D = exp(-(1.0 - NdotH2) / (denom * 0.1)) / (PI * alpha * NdotH2 + 0.0001);
    
    // ========== 2. 棉布菲涅尔(非常弱) ==========
    float LdotH = dot(lightDir, halfVec);
    float3 F0 = float3(0.02, 0.02, 0.02); // 非常低的菲涅尔反射率
    float3 F = F0 + (1.0 - F0) * pow(1.0 - LdotH, 5.0);
    
    // ========== 3. 几何项(强遮蔽) ==========
    // 棉布表面粗糙,遮蔽严重
    float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
    float G = NdotL * NdotV / ((NdotL * (1.0 - k) + k) * (NdotV * (1.0 - k) + k));
    
    // ========== 4. 漫反射主导的高光混合 ==========
    // 棉布高光有色(与漫反射相关)
    float3 specularColor = albedo * 0.3;
    float3 specular = (D * F * G) / (4.0 * NdotL * NdotV + 0.0001);
    
    return specular * specularColor * 0.1; // 非常弱的高光
}

// 棉布完整的BRDF(漫反射主导)
float3 CottonBRDF(float3 normal, float3 viewDir, float3 lightDir,
                 float3 albedo, float roughness)
{
    // 主要使用Oren-Nayar漫反射
    float3 diffuse = OrenNayarDiffuse(normal, lightDir, viewDir, roughness, albedo);
    
    // 非常微弱的高光
    float3 specular = CottonSpecular(normal, viewDir, lightDir, roughness, albedo);
    
    return diffuse + specular;
}

 皮革 - 双层高光模型

物理原理

皮革有清漆层(coating) 和基底层。清漆层提供锐利高光,基底层提供柔和高光。

// 皮革双层高光模型
struct LeatherLayer
{
    float roughness;
    float strength;
    float3 F0;
    float thickness; // 用于干涉效应
};

float3 LeatherDualLayerSpecular(float3 normal, float3 viewDir, float3 lightDir,
                               LeatherLayer baseLayer, LeatherLayer coatingLayer)
{
    float3 halfVec = normalize(lightDir + viewDir);
    float NdotH = dot(normal, halfVec);
    float NdotL = dot(normal, lightDir);
    float NdotV = dot(normal, viewDir);
    float LdotH = dot(lightDir, halfVec);
    
    // ========== 1. 基底层高光 ==========
    // 基底较粗糙
    float alphaBase = baseLayer.roughness * baseLayer.roughness;
    float D_base = D_GGX(NdotH, alphaBase);
    float3 F_base = FresnelSchlick(LdotH, baseLayer.F0);
    float G_base = GeometrySmith(NdotL, NdotV, baseLayer.roughness);
    
    float3 specularBase = (D_base * F_base * G_base) / (4.0 * NdotL * NdotV + 0.0001);
    
    // ========== 2. 清漆层高光 ==========
    // 清漆层较光滑
    float alphaCoating = coatingLayer.roughness * coatingLayer.roughness;
    float D_coating = D_GGX(NdotH, alphaCoating);
    
    // 清漆层有更高的菲涅尔反射率
    float3 F_coating = FresnelSchlick(LdotH, coatingLayer.F0);
    float G_coating = GeometrySmith(NdotL, NdotV, coatingLayer.roughness);
    
    float3 specularCoating = (D_coating * F_coating * G_coating) / (4.0 * NdotL * NdotV + 0.0001);
    
    // ========== 3. 层间干涉 ==========
    // 清漆层与基底层之间的干涉
    float interference = 0.0;
    if (coatingLayer.thickness > 0.0)
    {
        // 简化干涉模型
        float phase = coatingLayer.thickness * 100.0 * (1.0 - LdotH);
        interference = 0.5 + 0.5 * cos(phase);
    }
    
    // ========== 4. 能量守恒混合 ==========
    // 清漆层会遮挡基底层
    float coatingTransmission = 1.0 - F_coating.r; // 近似透射率
    
    float3 finalSpecular = specularBase * coatingTransmission * baseLayer.strength +
                          specularCoating * coatingLayer.strength * (1.0 + interference * 0.2);
    
    return finalSpecular;
}

// 皮革老化效果(随时间变化)
float3 LeatherAging(float3 specular, float age, float3 positionWS)
{
    // 模拟皮革老化:高光变暗、变粗糙
    float ageDarkening = exp(-age * 0.5);
    float ageRoughening = saturate(age * 0.3);
    
    // 磨损区域(如边缘、褶皱处)
    float3 worldNormal = normalize(cross(ddx(positionWS), ddy(positionWS)));
    float wear = 1.0 - saturate(dot(worldNormal, float3(0, 1, 0)));
    wear = pow(wear, 2.0);
    
    // 磨损导致高光减弱
    specular *= ageDarkening * (1.0 - wear * 0.7);
    
    // 添加划痕微高光
    float scratchNoise = fbm(positionWS * 10.0);
    float scratches = step(0.95, scratchNoise) * 0.1;
    specular += scratches * age;
    
    return specular;
}

羊毛 - 绒毛高光模型

物理原理

羊毛没有镜面高光,但有绒毛光泽(fuzz sheen),来自纤维末端的背向散射

// 羊毛绒毛高光模型(实际上几乎没有镜面高光)
float3 WoolSheen(float3 normal, float3 viewDir, float3 lightDir,
                float fuzzAmount, float fiberLength)
{
    // 羊毛的高光主要来自绒毛的微反射
    
    // ========== 1. 绒毛法线扰动 ==========
    // 绒毛使表面法线随机化
    float3 fuzzNormal = normal;
    
    // 添加随机扰动(基于位置)
    float3 positionWS = GetPositionWS();
    float3 randomOffset = float3(
        fbm(positionWS * 5.0),
        fbm(positionWS * 5.0 + float3(100, 0, 0)),
        fbm(positionWS * 5.0 + float3(0, 100, 0))
    ) * 2.0 - 1.0;
    
    fuzzNormal += randomOffset * fuzzAmount * fiberLength;
    fuzzNormal = normalize(fuzzNormal);
    
    // ========== 2. 背向散射光泽 ==========
    // 当光线从背面照射时,绒毛会发光
    float NdotL = dot(fuzzNormal, lightDir);
    float VdotN = dot(viewDir, normal);
    
    // 背向散射项(当光线和视线在法线两侧时)
    float backScatter = saturate(-NdotL * 0.5 + 0.5);
    backScatter = pow(backScatter, 2.0) * fuzzAmount;
    
    // ========== 3. 边缘光泽 ==========
    // 边缘处的绒毛更明显
    float edgeFactor = 1.0 - saturate(VdotN);
    edgeFactor = pow(edgeFactor, 3.0) * 2.0;
    
    // ========== 4. 绒毛微高光 ==========
    // 单个纤维末端的微弱高光
    float3 halfVec = normalize(lightDir + viewDir);
    float NdotH = dot(fuzzNormal, halfVec);
    
    // 非常宽泛的高光
    float fiberSpec = pow(saturate(NdotH), 10.0) * 0.01 * fuzzAmount;
    
    // ========== 5. 组合 ==========
    float3 sheen = (backScatter + edgeFactor + fiberSpec) * fuzzAmount;
    
    // 羊毛高光是单色的,类似白色/米色
    return sheen * float3(1.0, 0.98, 0.95);
}

// 完整羊毛BRDF(无镜面高光)
float3 WoolBRDF(float3 normal, float3 viewDir, float3 lightDir,
               float3 albedo, float roughness, float fuzzAmount, float thickness)
{
    // 漫反射(使用次表面散射增强)
    float NdotL = dot(normal, lightDir);
    float3 diffuse = LambertDiffuse(albedo, NdotL);
    
    // 次表面散射
    float3 subsurface = SubsurfaceScattering(normal, viewDir, lightDir, thickness);
    diffuse += subsurface * 0.5;
    
    // 绒毛光泽(替代传统高光)
    float3 sheen = WoolSheen(normal, viewDir, lightDir, fuzzAmount, 0.5);
    
    return diffuse * albedo + sheen;
}

天鹅绒 - 背向散射高光模型

物理原理

天鹅绒有特殊的方向性纤维,导致逆光时更亮(backward scattering)。

// 天鹅绒背向散射模型
float3 VelvetBackscattering(float3 normal, float3 viewDir, float3 lightDir,
                           float roughness, float pileLength, float3 albedo)
{
    // 天鹅绒纤维方向(通常垂直于表面)
    float3 fiberDirection = normal;
    
    // ========== 1. 背向散射核心 ==========
    // 当光线方向与视图方向在法线同侧时,发生背向散射
    float NdotL = dot(normal, lightDir);
    float NdotV = dot(normal, viewDir);
    
    // 背向散射强度:当NdotL和NdotV都小(掠射角)时最强
    float backScatter = (1.0 - abs(NdotL)) * (1.0 - abs(NdotV));
    backScatter = pow(backScatter, 2.0);
    
    // ========== 2. 纤维方向性 ==========
    // 纤维导致的各向异性背向散射
    float LdotFiber = dot(lightDir, fiberDirection);
    float VdotFiber = dot(viewDir, fiberDirection);
    
    // 当光线和视线都与纤维方向接近垂直时,背向散射最强
    float fiberEffect = (1.0 - abs(LdotFiber)) * (1.0 - abs(VdotFiber));
    fiberEffect = pow(fiberEffect, 3.0);
    
    // ========== 3. 颜色效果 ==========
    // 天鹅绒背向散射有颜色偏移(向红色偏移)
    float3 backscatterColor = albedo;
    backscatterColor.r *= 1.2; // 增强红色
    backscatterColor.b *= 0.8; // 减弱蓝色
    
    // ========== 4. 纤维密度影响 ==========
    // 纤维越密,背向散射越强
    float densityEffect = saturate(pileLength * 2.0);
    
    // ========== 5. 最终背向散射 ==========
    float3 backscattering = backScatter * fiberEffect * densityEffect * backscatterColor;
    
    return backscattering * 2.0; // 天鹅绒背向散射很强
}

// 天鹅绒镜面高光(非常微弱)
float3 VelvetSpecular(float3 normal, float3 viewDir, float3 lightDir,
                     float roughness, float pileLength)
{
    // 天鹅绒几乎没有镜面高光
    // 只有非常微弱的纤维末端反射
    
    float3 halfVec = normalize(lightDir + viewDir);
    float NdotH = dot(normal, halfVec);
    float NdotL = dot(normal, lightDir);
    float NdotV = dot(normal, viewDir);
    
    if (NdotL <= 0.0 || NdotV <= 0.0)
        return 0.0;
    
    // 非常粗糙的分布
    float alpha = roughness * roughness;
    float alpha2 = alpha * alpha;
    float NdotH2 = NdotH * NdotH;
    
    float denom = NdotH2 * (alpha2 - 1.0) + 1.0;
    float D = alpha2 / (PI * denom * denom);
    
    // 弱菲涅尔
    float LdotH = dot(lightDir, halfVec);
    float3 F0 = float3(0.02, 0.02, 0.02);
    float3 F = F0 + (1.0 - F0) * pow(1.0 - LdotH, 5.0);
    
    // 几何项
    float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
    float G = NdotL * NdotV / ((NdotL * (1.0 - k) + k) * (NdotV * (1.0 - k) + k));
    
    // 非常微弱的高光
    float3 specular = (D * F * G) / (4.0 * NdotL * NdotV + 0.0001);
    
    return specular * 0.05; // 强度非常低
}

// 完整天鹅绒BRDF
float3 VelvetBRDF(float3 normal, float3 viewDir, float3 lightDir,
                 float3 albedo, float roughness, float pileLength)
{
    // 漫反射(天鹅绒漫反射也很弱)
    float NdotL = dot(normal, lightDir);
    float3 diffuse = LambertDiffuse(albedo, NdotL) * 0.5; // 较暗
    
    // 背向散射(主要视觉效果)
    float3 backscattering = VelvetBackscattering(normal, viewDir, lightDir, 
                                                roughness, pileLength, albedo);
    
    // 微弱镜面高光
    float3 specular = VelvetSpecular(normal, viewDir, lightDir, roughness, pileLength);
    
    return diffuse + backscattering + specular;
}

合成纤维 - 均匀高光+斜射光泽

物理原理

合成纤维有均匀的规则结构,产生均匀高光,加上斜射时的额外光泽(sheen)。

// 合成纤维高光模型
float3 SyntheticFiberSpecular(float3 normal, float3 viewDir, float3 lightDir,
                             float roughness, float sheenStrength, float uniformity)
{
    float3 halfVec = normalize(lightDir + viewDir);
    float NdotH = dot(normal, halfVec);
    float NdotL = dot(normal, lightDir);
    float NdotV = dot(normal, viewDir);
    float LdotH = dot(lightDir, halfVec);
    
    // ========== 1. 基础镜面高光 ==========
    // 合成纤维有均匀的镜面高光
    float alpha = roughness * roughness;
    float alpha2 = alpha * alpha;
    float NdotH2 = NdotH * NdotH;
    
    float denom = NdotH2 * (alpha2 - 1.0) + 1.0;
    float D = alpha2 / (PI * denom * denom);
    
    // 合成纤维菲涅尔(比天然纤维强)
    float3 F0 = float3(0.05, 0.05, 0.05);
    float3 F = F0 + (1.0 - F0) * pow(1.0 - LdotH, 5.0);
    
    // 几何项
    float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
    float G = NdotL * NdotV / ((NdotL * (1.0 - k) + k) * (NdotV * (1.0 - k) + k));
    
    float3 specularBase = (D * F * G) / (4.0 * NdotL * NdotV + 0.0001);
    
    // ========== 2. 斜射光泽 (Sheen) ==========
    // 合成纤维在掠射角有额外光泽
    float sheen = 0.0;
    if (sheenStrength > 0.0)
    {
        // 使用Charlie分布模拟sheen
        float charlieAlpha = roughness * 2.0; // sheen更宽
        float charlieD = (2.0 + 1.0 / charlieAlpha) * 
                        pow(1.0 - NdotH * NdotH, 1.0 / (2.0 * charlieAlpha)) / 
                        (2.0 * PI);
        
        // Sheen的菲涅尔不同
        float3 sheenF = F0 + (float3(0.3, 0.3, 0.3) - F0) * pow(1.0 - LdotH, 3.0);
        
        sheen = charlieD * sheenF.r * sheenStrength;
    }
    
    // ========== 3. 均匀性处理 ==========
    // 合成纤维高光非常均匀
    float uniformFactor = uniformity;
    specularBase = lerp(specularBase, specularBase * 0.8 + 0.2, uniformFactor);
    
    // ========== 4. 组合 ==========
    return specularBase + sheen;
}

二.实现

1.布料漫反射 - Oren-Nayar

原理
Oren-Nayar模型准确地模拟了布料微表面材质的光线散射行为。考虑了表面粗糙度对漫反射的影响。

float3 ClothDiffuse(float3 albedo, float3 normal, float3 lightDir, 
                    float3 viewDir, float roughness)
{
    // 计算表面粗糙度参数
    float sigma = roughness * PI / 2.0;
    float sigma2 = sigma * sigma;
    
  
    float A = 1.0 - 0.5 * sigma2 / (sigma2 + 0.33);
    float B = 0.45 * sigma2 / (sigma2 + 0.09);

    float NdotL = max(dot(normal, lightDir), 0.001);
    float NdotV = max(dot(normal, viewDir), 0.001);
    

    float3 Lproj = normalize(lightDir - normal * NdotL);
    float3 Vproj = normalize(viewDir - normal * NdotV);
    float cosPhi = dot(Lproj, Vproj);
    
  
    float diffuse = NdotL * (A + B * max(0.0, cosPhi) * sqrt(1.0 - NdotL * NdotL));
    return albedo * diffuse;
}

2. 布料高光模型 - Charlie NDF

原理
Charlie NDF(正态分布函数)专门用于模拟布料和织物表面的微表面分布。相比传统的GGX或Beckmann模型,Charlie NDF能产生更柔和、更符合布料特性的高光。

float Charlie(float NdotH, float roughness)
{
    roughness = max(roughness, 0.001);
    float invRoughness = 1.0 / roughness;
    float sin2Theta = 1.0 - NdotH * NdotH;
    float exponent = (2.0 + invRoughness) * 0.5;
    return (2.0 + invRoughness) * pow(sin2Theta, exponent * 0.5) / (2.0 * PI);
}

3. 镭射效果

原理
基于视角相关的颜色映射,通过Ramp贴图实现动态色彩变化。使用NdotV(法线与视线点积)控制颜色变化

Ramp贴图

float3 CalculateEnhancedFoilEffect(float NdotV, float foilMask, 
                                   float3 normalWS, float3 viewDirWS)
{
   
    float foilUVX = saturate(NdotV * 0.5 + 0.5);
    foilUVX = lerp(foilUVX, 0.5, _FoilRoughness * 0.2);
    
    float3 rampColor = SAMPLE_TEXTURE2D(_RampMap, sampler_BaseMap, float2(foilUVX, 0.5)).rgb;
    rampColor = ProcessColor(rampColor);
    
    float edgeFactor = 1.0 - pow(1.0 - NdotV, 2.0) * 0.5 + 1.0;
    
    return rampColor * _FoilIntensity * foilMask * edgeFactor;
}

4.绒毛效果(Fuzz)

原理
模拟布料表面的微小纤维产生的背向散射效果。添加法线扰动和背向散射使用负法线点积的光照

float3 CalculateFuzz(float3 normal, float3 viewDir, float3 lightDir, float fuzzAmount)
{
    // 绒毛法线扰动
    float3 randomOffset = float3(
        sin(_Time.y * 2.0 + normal.x * 10.0) * 0.1,
        cos(_Time.y * 1.5 + normal.y * 10.0) * 0.1,
        0
    );
    
    float3 fuzzNormal = normalize(normal + randomOffset * fuzzAmount);
    
    // 背向散射计算
    float NdotL = dot(fuzzNormal, lightDir);
    float backScatter = saturate(-NdotL * 0.5 + 0.5);
    backScatter = pow(backScatter, 2.0);
    
    return backScatter * fuzzAmount * 0.3;
}

参考资料

从0开始的高级角色渲染 —— 布料

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐