头发的生成以及渲染方案

搁笔良久,今起复耕

本文主要涉及头发的生长方案,光照模型,阴影效果,透明效果以及多次采样抗锯齿。

一. 头发的生长:

       定义根节点以及头发长度参数

       头发从头皮生长,根据mesh的UV展开图,编辑头部头发生长区域以及利用颜色控制头发的长度。 鉴于头发后期仿真模拟的需要,此处使用tessellation shader,可以生长更加细密的头发。

       对头部头发生长区域mesh着色(头发颜色),消除头发和头皮颜色误差

       vec3 color = mix(texture2D(texcolor), hairColor, texture2D(glowmap).r); 其中 glowmap 即上面编辑得到头皮的颜色部分, texcolor 为头部mesh 本来的颜色。

       控制后续头发走向,形成发型

       得到头发的生长根节点之后,需要控制后面节点的生长。利用向量,控制每根头发的点的走向。 

     

          Image result for hair rendering picture

二、 头发的光照模型

        Kajiaya 光照模型: 主要特点即 tangent 方向为沿头发方向; 使用该模型,得到的头发渲染效果,会有较逼真的光圈效果

            Image result for hair rendering picture

 

       Kajiya & Kay. “Rendering furwith Three Dimensional Textures.” Computer Graphics (Proceedings of ACMSIGGRAPH 89), 1989.

 

             diffuse = sqrt(1. - abs(dot(tangent_N.xyz, light_N.xyz)));       specular = pow(sqrt(1. - abs(dot(tangent_N, h_N))), shinness); 其中h_N = normalize(eye + light)

三、自阴影效果

       DOP shadow

          

   

       Yuskel & Keyser. “DeepOpacity Maps.” Proceedings of EUROGRAPHICS, 2008.  

   简述下“Deep Opacity Maps” 的方法。根据光源距离深度划分为几个深度层(即Deep opacity map), 计算occlusion并求和,然后 transmittance=  exp(-occlusion * shadowIntensity);头发的系数 hairColor * Transmittance 得到不同头发的阴影效果。

四、Transparency 效果

    

 

Everitt, Cass. “InteractiveOrder-Independent Transparency.” Technical Report, NVIDIA Corporation. 2001.

 

    可以查阅 深度剥离 的透明方法;

五、superSampling- 4XSSAA

        关于SSAA, 定义2*width 以及 2* heighth 的render texture, 然后 renderFullScreen

 

Reference:  

        文中已经配有;
 

Codes:

https://github.com/mravella/hair

 

 

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
头发各向异性渲染Shader 这个是04年的一个ppt,主要介绍了头发渲染,其追到源头还是要看这个原理。 各向异性的主要计算公式: 主要代码如下: 切线混合扰动部分(这部分也可以用T+k*N,来对切线进行扰动): float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir); float3 _T_var = UnpackNormal(tex2D(_Tangent, TRANSFORM_TEX(i.uv0, _Tangent))); float3 temp = lerp(_TangentParam.xyz, _T_var, _BlenfTangent); float3 T = normalize(mul(float3(temp.xy,0), tangentTransform)); 主要是通过改变切线的xy值来造成头发高光部分的多样性。 高光部分,按公式计算即可: float StrandSpecular(float3 T, float3 V, float3 L, float exponent) { float3 H = normalize(L + V); float dotTH = dot(T, H); float sinTH = sqrt(1 - dotTH*dotTH); float dirAtten = smoothstep(-1, 0, dotTH); return dirAtten*pow(sinTH, exponent); } 注意,为了模拟的更贴近真实性,应用两层高光,第一层高光代表直射光直接反射出去,第二层代表次表面散射现象具体看代码。 最终渲染部分: float4 HairLighting(float3 T, float3 N, float3 L, float3 V, float2 uv, float3 lightColor) { float diffuse = saturate(lerp(0.25, 1.0, dot(N, L)))*lightColor; float3 indirectDiffuse = float3(0, 0, 0); indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; // Ambient Light float3 H = normalize(L + V); float LdotH = saturate(dot(L, H)); float3 specular = _Specular*StrandSpecular(T, V, L, exp2(lerp(1, 11, _Gloss))); //float specMask = tex2D(_SpecMask, TRANSFORM_TEX(uv, _SpecMask)); specular += /*specMask*/_SubColor*StrandSpecular(T, V, L, exp2(lerp(1, 11, _ScatterFactor))); float4 final; float4 base = tex2D(_MainTex, TRANSFORM_TEX(uv, _MainTex)); float3 diffuseColor = (_Color.rgb*base.rgb); //float ao = tex2D(_AO, TRANSFORM_TEX(uv, _AO)).g; final.rgb = (diffuse + indirectDiffuse)*diffuseColor + specular*lightColor* FresnelTerm(_Specular, LdotH); //final.rgb *= ao; final.a = base.a; clip(final.a - _CutOff); return final; } 这里我注释掉了AO和高光遮罩,需要的同学可以加上。 最后一点为了不让头发的边经过clip之后太硬,需要进行两个通道的belnd。 第二个pass使用以下指令: Blend SrcAlpha OneMinusSrcAlpha ZWrite Off 注意第二个通道无需再进行clip操作。 至此,头发渲染完毕。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不负初心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值