纳金网
标题: 汽车喷漆效果的实现 [打印本页]
作者: star-小虎 时间: 2013-10-15 16:12
标题: 汽车喷漆效果的实现
给汽车身体喷漆是一个复杂的过程,车身油漆是昂贵分层形式,往往包含染料层,搪瓷金属箔悬浮层.
由于这些接二连三油漆表面层,展示出了一种复杂的光学交互,使车看起来平滑,光泽。
完整的HLSL像素着色器代码如下:
struct PsInput
{
float2 Tex : TEXCOORD0;
float3 Tangent : TEXCOORD1;
float3 Binormal : TEXCOORD2;
float3 Normal : TEXCOORD3;
float3 View : TEXCOORD4;
float3 SparkleTex : TEXCOORD5;
};
float4 main(PsInput i) : COLOR
{
// 取得当前的法线图
float3 vNormal = tex2D( normalMap, i.Tex );
// 缩放和偏移让其在[-1.0, 1.0]区域内:
vNormal = 2.0f * vNormal - 1.0f;
// 获得高频率扰动的法线,通过查询一个噪声图。
float3 vFlakesNormal = tex2D(microflakeNMap, i.SparkleTex);
// 别忘了转换到 [-1.0, 1.0] 区域内:
vFlakesNormal = 2 * vFlakesNormal - 1.0;
// 计算以下公式
// Np1 = ( a * Np + b * N ) / || a * Np + b * N || where a << b
//
float3 vNp1 = microflakePerturbationA * vFlakesNormal + normalPerturbation * vNormal ;
// 计算以下公式
// Np2 = ( c * Np + d * N ) / || c * Np + d * N || where c == d
float3 vNp2 = microflakePerturbation * ( vFlakesNormal + vNormal ) ;
// 因为需要与法线点乘求夹角,所以我们必须将它归一化一下
float3 vView = normalize( View );
// 把表面法线转换好世界空间中来,计算bump map的方法。
float3x3 mTangentToWorld = transpose( float3x3( Tangent, Binormal, Normal ) );
float3 vNormalWorld = normalize( mul( mTangentToWorld, vNormal ));
// 计算夹角余玄
float fNdotV = saturate(dot( vNormalWorld, vView));
// 计算出反射向量
float3 vReflection = 2 * vNormalWorld * fNdotV - vView;
// 我们需要一个gloss值来读环境图,在真实的demo中,反射效果会有轻微的模糊。
float fEnvBias = glossLevel;
// 用反射向量采样环境图。
float4 envMap = texCUBEbias( showroomMap, float4( vReflection, fEnvBias ) );
//乘以亮度值,在a通道中储存 RGBE
envMap.rgb = envMap.rgb * envMap.a;
// 再乘以一个亮度系数
envMap.rgb *= brightnessFactor;
// 将切线空间中的法线变换到世界坐标中来.
float3 vNp1World = normalize( mul( mTangentToWorld, vNp1) );
// 法线和视线点乘,得到斐涅尔系数
float fFresnel1 = saturate( dot( vNp1World, vView ));
// 将第二个法线也同样重切线空间中变换到世界坐标中来.
float3 vNp2World = normalize( mul( mTangentToWorld, vNp2 ));
// 同样的方法得到第二个斐涅尔系数.
float fFresnel2 = saturate( dot( vNp2World, vView ));
// 开始合成所有层了.
// 根据公式三
float fFresnel1Sq = fFresnel1 * fFresnel1;
float4 paintColor = fFresnel1 * paintColor0 +
fFresnel1Sq * paintColorMid +
fFresnel1Sq * fFresnel1Sq * paintColor2 +
pow( fFresnel2, 16 ) * flakeLayerColor;
// 最后与反射的环境贴图合成在一起,形成最终的结果.
float fEnvContribution = 1.0 - 0.5 * fNdotV;
float4 finalColor;
finalColor.a = 1.0;
finalColor.rgb = envMap * fEnvContribution + paintColor;
return finalColor;
}
结论
此代码所使用的算法,经验更大于真实的物理属性,所以需要不断得调整常数值,
来使最终得到一个满意的效果.
作者: HIDEOKOJIMA 时间: 2013-10-15 16:44
Thanks for sharing !
作者: tangqizuse 时间: 2013-10-16 22:18
谢谢楼主,学习了
作者: 幸福小猪 时间: 2013-10-28 10:42
感谢楼主分享
作者: gxf5168 时间: 2014-2-24 02:08
谢谢分享
作者: orokborokhulu 时间: 2014-2-24 09:43
感谢分享
作者: BlueGem 时间: 2014-2-24 15:50
感谢分享
作者: Anny123 时间: 2018-12-27 20:50
你好,我看了汽车喷漆效果的实现 这个帖子,有两个问题想请教你,切线转换到世界坐标系下是法线乘以TBN矩阵还是法线乘以TBN的逆矩阵,代码里面的View是什么东西,希望知道的朋友回答我一下哦,谢谢
欢迎光临 纳金网 (http://old.narkii.com/club/) |
Powered by Discuz! X2.5 |