问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Unity Shader实现丝袜布料渲染效果

创作时间:
作者:
@小白创作中心

Unity Shader实现丝袜布料渲染效果

引用
51CTO
1.
https://blog.51cto.com/u_16099218/13391191

在Unity引擎中实现逼真的布料渲染效果是一个挑战,特别是对于像丝袜这样具有特殊材质特性的布料。本文将详细介绍如何通过Shader编程来实现丝袜的渲染效果,包括丹尼尔值、纤维特性等关键参数的计算和应用。

Unity Shader 布料渲染(丝袜)

  • 现实中的丝袜效果
  • 丹尼尔值
  • 纤维的特性
  • 分析
  • 效果截图:
  • Weak:
  • Normal:
  • Strong:
  • 属性值定义:
  • 丹尼尔值与拉伸程度
  • 边缘度的计算
  • 完整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"
}

本文原文来自51cto.com

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号