I’ve found a nifty little car paint shader from ATi, and I was wondering if it can be “translated” for Unity. I’m pretty much a shader noob and was wondering if it’s possible.
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
{
// fetch from the incoming normal map:
float3 vNormal = tex2D( normalMap, i.Tex );
// Scale and bias fetched normal to move into [-1.0, 1.0] range:
vNormal = 2.0f * vNormal - 1.0f;
// Micro-flakes normal map is a high frequency normalized
// vector noise map which is repeated across the surface.
// Fetching the value from it for each pixel allows us to
// compute perturbed normal for the surface to simulate
// appearance of micro-flakes suspended in the coat of paint:
float3 vFlakesNormal = tex2D(microflakeNMap, i.SparkleTex);
// Don't forget to bias and scale to shift color into [-1.0, 1.0] range:
vFlakesNormal = 2 * vFlakesNormal - 1.0;
// This shader simulates two layers of micro-flakes suspended in
// the coat of paint. To compute the surface normal for the first layer,
// the following formula is used:
// Np1 = ( a * Np + b * N ) / || a * Np + b * N || where a << b
//
float3 vNp1 =
microflakePerturbationA * vFlakesNormal + normalPerturbation * vNormal ;
// To compute the surface normal for the second layer of micro-flakes, which
// is shifted with respect to the first layer of micro-flakes, we use this formula:
// Np2 = ( c * Np + d * N ) / || c * Np + d * N || where c == d
float3 vNp2 = microflakePerturbation * ( vFlakesNormal + vNormal ) ;
// The view vector (which is currently in world space) needs to be normalized.
// This vector is normalized in the pixel shader to ensure higher precision of
// the resulting view vector. For this highly detailed visual effect normalizing
// the view vector in the vertex shader and simply interpolating it is insufficient
// and produces artifacts.
float3 vView = normalize( View );
// Transform the surface normal into world space (in order to compute reflection
// vector to perform environment map look-up):
float3x3 mTangentToWorld = transpose( float3x3( Tangent, Binormal, Normal ) );
float3 vNormalWorld = normalize( mul( mTangentToWorld, vNormal ));
// Compute reflection vector resulted from the clear coat of paint on the metallic
// surface:
float fNdotV = saturate(dot( vNormalWorld, vView));
float3 vReflection = 2 * vNormalWorld * fNdotV - vView;
// Here we just use a constant gloss value to bias reading from the environment
// map, however, in the real demo we use a gloss map which specifies which
// regions will have reflection slightly blurred.
float fEnvBias = glossLevel;
// Sample environment map using this reflection vector:
float4 envMap = texCUBEbias( showroomMap, float4( vReflection, fEnvBias ) );
// Premultiply by alpha:
envMap.rgb = envMap.rgb * envMap.a;
// Brighten the environment map sampling result:
envMap.rgb *= brightnessFactor;
// Compute modified Fresnel term for reflections from the first layer of
// microflakes. First transform perturbed surface normal for that layer into
// world space and then compute dot product of that normal with the view vector:
float3 vNp1World = normalize( mul( mTangentToWorld, vNp1) );
float fFresnel1 = saturate( dot( vNp1World, vView ));
// Compute modified Fresnel term for reflections from the second layer of
// microflakes. Again, transform perturbed surface normal for that layer into
// world space and then compute dot product of that normal with the view vector:
float3 vNp2World = normalize( mul( mTangentToWorld, vNp2 ));
float fFresnel2 = saturate( dot( vNp2World, vView ));
// Combine all layers of paint as well as two layers of microflakes
float fFresnel1Sq = fFresnel1 * fFresnel1;
float4 paintColor = fFresnel1 * paintColor0 +
fFresnel1Sq * paintColorMid +
fFresnel1Sq * fFresnel1Sq * paintColor2 +
pow( fFresnel2, 16 ) * flakeLayerColor;
// Combine result of environment map reflection with the paint color:
float fEnvContribution = 1.0 - 0.5 * fNdotV;
float4 finalColor;
finalColor.a = 1.0;
finalColor.rgb = envMap * fEnvContribution + paintColor;
return finalColor;
}