次时代游戏头发各项异性流光flowtexture绘制探析

本文分享了中国风Q版次世代头发FlowTexture的绘制方法,通过分析《梦幻西游三维版》牛魔头发的flowtexture,提出了一种更高效、效果更好的流程。包括在SP中烘焙World Space Normal贴图,提取R和G通道,调整曲率图(Curvature)以匹配B通道,最后在PS中组合成flowtexture,并添加A通道作为头发与头饰的mask。
摘要由CSDN通过智能技术生成

       一直以来忙于次时代项目研发工作,少有时间去好好总结沉淀一下,半年前就打算想写点东西分享交流一下,直到今天才有时间真正去执笔。

       参与过次时代项目的同学,大多都接触过一个各项异性的概念,今天我想分享的内容是中国风Q版次时代头发各项异性flowtexture的绘制方法。

       网上大家都很容易搜到一篇关于flowtexture绘制流程方法的文章,笔者也曾按照网上的方法在SP中实际的去操作尝试过,切身的体会是网上的绘制方法并不能得到我们想要的较为完美的flowtexture贴图,且绘制的过程很难受,效果很糟糕,绘制效率也很低;

        下图是按照网上讲的方法在SP中绘制的flowtexture效果图,色块很乱,不受控制,没有丝滑的感觉;


        为了高效便捷的解决问题,笔者找到了一张《梦幻西游三维版》中的一个牛魔头发的flowtexture图,经过对贴图通道的拆解、分析、测试和实际绘制尝试,通过分析研究和实践操作总结出来一套流程简化、效率和效果都得到提升的实用方法;

现将整个流程归纳表述如下:

(1)我们通过对牛魔头发flowtexture的R、G、B和A通道的研究分析发现,flowtexture的R通道和G通道与SP中渲染生成的World Space normal的R通道和G通道的灰度值信息非常的接近和相似;

头发各向异性渲染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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值