# How to do Triplanar Texturing

Ok maybe i'm missing something because its getting late and i've been programming now for about 72 hours straight (minus a nap or 2) ...

I'm trying to write a shader for unity that will apply triplanar texturing to a mesh, here's my shader code ...

Shader "My Shaders/TriPlanar" {
Properties {
Tex1 ("Texture 1", 2D) = "white" {}
Tex2 ("Texture 2", 2D) = "white" {}
Tex3 ("Texture 3", 2D) = "white" {}
}

SubShader {
Pass {
CGPROGRAM
#pragma target 3.0
#pragma glsl
#pragma vertex Vert
#pragma fragment Frag
#include "UnityCG.cginc"

sampler2D Tex1;
sampler2D Tex2;
sampler2D Tex3;

struct data
{
float4 position : POSITION;
float3 normal;
float4 uv : TEXCOORD0;
};

data Vert(appdata_base v)
{
data res;
res.position = mul( UNITY_MATRIX_MVP, v.vertex);
res.normal = v.normal;
res.uv = v.texcoord;
return res;
}

float4 Frag( data input ) : COLOR
{
float4 result;

float norX = abs(input.normal.x);
float norY = abs(input.normal.y);
float norZ = abs(input.normal.z);

float total = (norX + norY + norZ);
norX /= total;
norY /= total;
norZ /= total;

// get sample from tex1 and apply norX amount to pixel color
float4 texXZ = tex2D(Tex1, input.uv.xz);
float4 texXY = tex2D(Tex1, input.uv.xy);
float4 texYZ = tex2D(Tex1, input.uv.yz);
result = (texXZ * norX);

// get sample from tex2 and blend norY amount
texXZ = tex2D(Tex2, input.uv.xz);
texXY = tex2D(Tex2, input.uv.xy);
texYZ = tex2D(Tex2, input.uv.yz);
result += (texXY * norY);

// get sample from tex3 and blend norZ amount
texXZ = tex2D(Tex3, input.uv.xz);
texXY = tex2D(Tex3, input.uv.xy);
texYZ = tex2D(Tex3, input.uv.yz);
result += (texYZ * norZ);

return result;
}
ENDCG
}
}
}


The problem is that I only get 1 pixels worth of sample from the texture so I end up ultimately just "colouring" the verts instead of actually texturing them.

How do I tell my shader to build a colour that results in the texture being drawn not just 1 corner pixels worth of it?

EDIT:

The code in the shader is an implementation of a vertex and fragment but the fragment part came from a pixel shader ... i don't understand the difference there (my first problem)

I can't say i've ever written a fragment shader before (a second problem)

Also i'm not setting any uv's in my cpu code (a problem when I come to use my shader but i'll face that later) ... odd that I get anything at all to be honest, however I'm applying this to a cube game object generated by unity and I get strips of texture so i can't be that far off.

• A pixel shader is an interchangeable term with fragment shader. Also, think about how the pipeline works. Vertex shaders act as per vertex operations, while pixel shaders act as per pixel operations. The only objective of most pixel shaders is indeed to generate a color, whether that means sampling a texture for color or simply using a diffuse + ambient + lightbulb or whatever. If you aren't passing in any UV coordinates to the vertex shader, then you will either need to manually set them in the shader to test, or pass them in. Otherwise you wont be able to accurately sample the texture. – Evan Apr 8 '13 at 13:41
• I agree, I have been testing this on a cube before I apply it to my game mesh as the scenario is much less complex and the cube is helping me loads to get the code working. I've managed to get 1 of the planes working the way I'd expect but the others are showing lines of colour rather than the texture. I'll update the question with the latest code right now ... – War Apr 8 '13 at 14:41
• There we go, if you pull that in to unity and load it you should be able to see the problem right away "texture top and bottom" and "streaks round the sides" (when given a cube) ... i'm sure it's just a math thing i've messed up on here. – War Apr 8 '13 at 14:43

## 1 Answer

Um ... well ... it's a pretty basic example of triplanar texturing but it works ...

Shader "My Shaders/TriPlanar" {
Properties {
Tex1 ("Texture 1", 2D) = "white" {}
Tex2 ("Texture 2", 2D) = "white" {}
Tex3 ("Texture 3", 2D) = "white" {}
}

SubShader {
Pass {
CGPROGRAM
#pragma target 3.0
#pragma glsl
#pragma vertex Vert
#pragma fragment Frag
#include "UnityCG.cginc"

sampler2D Tex1;
sampler2D Tex2;
sampler2D Tex3;

struct data
{
float4 position : POSITION;
float3 normal;
float4 uv : TEXCOORD0;
};

data Vert(appdata_base v)
{
data res;
res.position = mul( UNITY_MATRIX_MVP, v.vertex);
res.normal = v.normal;
res.uv = v.texcoord;
return res;
}

float4 Frag( data input ) : COLOR
{
float4 result;

float norX = abs(input.normal.x);
float norY = abs(input.normal.y);
float norZ = abs(input.normal.z);

float total = (norX + norY + norZ);
norX /= total;
norY /= total;
norZ /= total;

// get sample from tex1 and apply norX amount to pixel color
float4 texXY = tex2D(Tex1, input.uv.xy);
result = (texXY * norX);

// get sample from tex2 and blend norY amount
texXY = tex2D(Tex2, input.uv.xy);
result += (texXY * norY);

// get sample from tex3 and blend norZ amount
texXY = tex2D(Tex3, input.uv.xy);
result += (texXY * norZ);

return result;
}
ENDCG
}
}
}


Now I just need to add in things like variances for lighting and such :)

I hope this is helpful to someone out there getting to grips with triplanar texturing :)