So I’m writing a surface shader to texture a procedural mesh and to solve textures from stretching I thought of applying triplanar mapping.
The way I am doing it is something like this:
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
o.wN = UnityObjectToWorldNormal(v.normal);
o.worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
// compute bitangent from cross product of normal and tangent
half tangentSign = v.tangent.w * unity_WorldTransformParams.w;
o.worldBitangent = cross(o.wN, o.worldTangent) * tangentSign;
}
I have a vertex shader that computes all the basis vectors of the TBN matrix that are later passed to compute the correct normals for the lighting.
float3x3 TBN = float3x3(normalize(IN.worldTangent), normalize(IN.worldBitangent), normalize(IN.wN)); // TANGENT TO WORLD
// calculate triplanar blend
half3 triblend = saturate(pow(IN.wN, 4));
triblend /= max(dot(triblend, half3(1, 1, 1)), 0.0001);
// calculate triplanar uvs
float2 uvX = IN.worldPos.zy;
float2 uvY = IN.worldPos.xz;
float2 uvZ = IN.worldPos.xy;
After creating the TBN matrix in the surface shader and computing the UVs of each axis projection i did the following:
//Triplanar sampling
float3 xProjection = UNITY_SAMPLE_TEX2DARRAY(_TexturesArray, float3(uvX, j)).rgb * triblend.x;
float3 yProjection = UNITY_SAMPLE_TEX2DARRAY(_TexturesArray, float3(uvY, j)).rgb * triblend.y;
float3 zProjection = UNITY_SAMPLE_TEX2DARRAY(_TexturesArray, float3(uvZ, j)).rgb * triblend.z;
return xProjection + yProjection + zProjection; //This is assigned to a variable called finalColor
float3 tnormalX = UnpackNormal(UNITY_SAMPLE_TEX2DARRAY(_NormalMaps, float3(uvX, j)));
float3 tnormalY = UnpackNormal(UNITY_SAMPLE_TEX2DARRAY(_NormalMaps, float3(uvY, j)));
float3 tnormalZ = UnpackNormal(UNITY_SAMPLE_TEX2DARRAY(_NormalMaps, float3(uvZ, j)));
float3 worldNormalX = mul(TBN, tnormalX);
float3 worldNormalY = mul(TBN, tnormalY);
float3 worldNormalZ = mul(TBN, tnormalZ);
// we apply triblending and contribution
return (worldNormalX * triblend.x + worldNormalY * triblend.y + worldNormalZ * triblend.z); //This is assigned to a variable called finalNormal
So basically I sample the normals which are in tangent space and convert them to world space in order to apply the blending.
Finally when i write to o.Normal i do the following to pass from world to tangent space back again:
o.Normal = mul(transpose(TBN), finalNormal);
but the results are weird looking, I guess light isn’t supposed to be there:
I would be grateful if someone could help me

