Unity Shader 布料渲染(丝袜)

现实中的丝袜效果

在这里插入图片描述
主要材质为 约90%聚酰胺纤维(锦纶/尼龙)+ 约10%聚氨酯纤维(氨纶)
基本上可以推测这种材质的金属性(Metallic)为0,而光滑度(Smoothness)则根据种类不同会有较大区别。

丹尼尔值

各种丝袜的厚薄也有区别,“D”或“Denier”是指纤维的纤度单位。5D、10D几乎透明,100D以上则几乎不透,很好理解,请看下图:
在这里插入图片描述
在Shader里我们采用Denier值来表示丝袜的厚薄程度。

纤维的特性

我们可以发现一种现象——靠近腿部中央的位置丝袜颜色较淡,并且如果丝袜够薄甚至会显出底下皮肤的颜色,而越靠近腿两侧丝袜颜色则会越深。丝袜由无数细小交错的纤维组成,所以正对视线的纤维是最稀疏的,而越靠近腿部轮廓的纤维则对于观察者来说越显得密集。
在这里插入图片描述

分析

基于PBR,对丝袜纤维的密集程度定义一个属性 疏密度(Density) ,取值范围0(几乎没有纤维)到 1(完全被纤维覆盖)。依据疏密度提供颜色给Albedo通道,疏密度越高显现更多丝袜颜色,越低则显现皮肤颜色。

计算疏密度需要三部步骤:
1.丹尼尔值对整体疏密度的影响。
2.受丝袜良好弹性影响,需要一张灰度贴图来控制不同区域的拉伸程度,拉伸越大疏密度越低。
3.受观察者视线的影响,丝袜平面与观察者视线角度越小时,疏密度越大。称其为边缘度影响。

效果截图:

Weak:

在这里插入图片描述

Normal:

在这里插入图片描述

Strong:

在这里插入图片描述

属性值定义:

    Properties{
        _Denier("Denier", Range(5,120)) = 25.0
        _DenierTex("Density Texture", 2D) = "black"{}
		_Smoothness("Smoothness", Range(0,1)) = 0.1
		_Metallic("Metallic",Range(0,1)) = 0.1
        [Enum(Strong,6,Normal,12,Weak,20)] _RimPower("Rim Power", float) = 12
		_FresnelScale("Fresnel Scale",Range(0, 6)) = 1
        _SkinTint("Skin Color Tint", Color) = (1,0.9,0.8,1)
        _SkinTex("Skin Color", 2D) = "white" {}
        _StockingTint("Stocking Color Tint", Color) = (1,1,1,1)
        _StockingTex("Stocking Color", 2D) = "white"{}
        _NormalTex("Normal", 2D) = "bump"{}
    }

丹尼尔值与拉伸程度

float denier = (_Denier - 5) / 115;
float density = denier * (1 - tex2D(_DenierTex, IN.uv_DenierTex));

边缘度的计算

float rim = pow(1 - dot(normalize(IN.viewDir), o.Normal), _RimPower / 10);   //边缘光
float fresnel = pow(1.0 - max(0,dot(normalize(IN.viewDir), o.Normal)),_FresnelScale);    //菲涅尔

完整Shader代码

Shader "Kirk/Stocking" {
    Properties{
        _Denier("Denier", Range(5,120)) = 25.0
        _DenierTex("Density Texture", 2D) = "black"{}
		_Smoothness("Smoothness", Range(0,1)) = 0.1
		_Metallic("Metallic",Range(0,1)) = 0.1
        [Enum(Strong,6,Normal,12,Weak,20)] _RimPower("Rim Power", float) = 12
		_FresnelScale("Fresnel Scale",Range(0, 6)) = 1
        _SkinTint("Skin Color Tint", Color) = (1,0.9,0.8,1)
        _SkinTex("Skin Color", 2D) = "white" {}
        _StockingTint("Stocking Color Tint", Color) = (1,1,1,1)
        _StockingTex("Stocking Color", 2D) = "white"{}
        _NormalTex("Normal", 2D) = "bump"{}
    }
    SubShader{
        Tags{ "RenderType" = "Opaque" }

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0

        struct Input {
            float2 uv_SkinTex;
            float2 uv_StockingTex;
            float2 uv_DenierTex;
            float2 uv_NormalTex;
            float3 viewDir;
        };

        float _RimPower;
        float _Denier;
        float _Smoothness;
		float _Metallic;
		float _FresnelScale;
        float4 _SkinTint;
        float4 _StockingTint;
        sampler2D _DenierTex;
        sampler2D _SkinTex;
        sampler2D _StockingTex;
        sampler2D _NormalTex;

        void surf(Input IN, inout SurfaceOutputStandard o) {
            o.Normal = UnpackNormal(tex2D(_NormalTex, IN.uv_NormalTex));  //得到法线
            float4 skinColor = tex2D(_SkinTex, IN.uv_SkinTex) * _SkinTint;    //内颜色
            float4 stockingColor = tex2D(_StockingTex, IN.uv_StockingTex) * _StockingTint;    //外颜色
            float rim = pow(1 - dot(normalize(IN.viewDir), o.Normal), _RimPower / 10);   //边缘光
			float fresnel = pow(1.0 - max(0,dot(normalize(IN.viewDir), o.Normal)),_FresnelScale);    //菲涅尔
            float denier = (_Denier - 5) / 115;    //丹尼尔参数
            float density = max(rim, (denier * (1 - tex2D(_DenierTex, IN.uv_DenierTex))));  //lerp参数
			
            o.Albedo = lerp(skinColor, stockingColor, density);
			o.Albedo = o.Albedo * (1 - fresnel);
            o.Metallic = _Metallic;
            o.Smoothness = _Smoothness;
        }
    ENDCG
    }
    FallBack "Diffuse"
}
  • 13
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值