**Quote: **"You mean calculating tangents inside vertex shader?"

Not quite - more of an ad hoc smoothing as in the extract below:

struct app_in
{
float4 pos : POSITION;
float3 normal : NORMAL0;
float3 tangent : TANGENT0;
float3 binormal : BINORMAL0;
float2 uv : TEXCOORD0;
};
struct vs_out
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
float3 tangent : TEXCOORD2;
float3 binormal : TEXCOORD3;
float4 wpos : TEXCOORD4;
};
vs_out VS( app_in IN )
{
vs_out OUT;
float4 pos = mul( IN.pos, WorldViewProj );
OUT.pos = pos;
OUT.wpos = mul( IN.pos, World );
OUT.uv = IN.uv;
float3 normal = normalize(mul(IN.normal.xyz,(float3x3)World ));
float3 tangent = normalize(mul(IN.tangent.xyz,(float3x3)World ));
float3 binormal = normalize(mul(IN.binormal.xyz,(float3x3)World ));
//smooth out the tangents and binormals with the normals
float3 b = normalize(cross( normal,tangent ));
b *= sign(dot(b,binormal));
float3 t = normalize(cross( normal,b ));
t *= sign(dot(t,tangent));
float3 t2 = normalize(cross( normal,binormal ));
t2 *= sign(dot(t2,tangent));
float3 b2 = normalize(cross( normal,t2 ));
b2 *= sign(dot(b2,binormal));
//pass normal, tangent, and binormal to pixel shader
OUT.normal = normal;
OUT.tangent = normalize((t+t2)*0.5);
OUT.binormal = normalize((b+b2)*0.5);
return OUT;
}

If I recall correctly that particular fix was suggested by Paul Johnston - although I usually use a slightly simpler variant of the same idea. But that fix assumes the normals are calculated correctly.