Hello! I made a project where a voxel terrain system uses a specific vertex color to determine the texture used for that voxel. This works fine - but has very sharp edges and looks quite bad. I was wondering if there’s any way to make the edges blend together.
Thanks! Current shader code below:
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader"Triplanar" {
Properties {
_ArrTex("TextureArr", 2DArray) = "" {}
scale("Scale", Float) = 1
_brightness("Texture Brightness", Float) = 1
_SpecColor("Specular Material Color", Color) = (1, 1, 1, 1)
_Shininess("Shininess", Float) = 10
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma multi_compile_fwdbase
#pragma vertex vert
#pragma fragment frag
#include"UnityCG.cginc"
#include"AutoLight.cginc"
struct v2f
{
float3 worldPos : TEXCOORD0;
half3 worldNormal : TEXCOORD1;
float4 pos : SV_POSITION;
float4 color : COLOR;
LIGHTING_COORDS(2, 3)
};
v2f vert(float4 vertex : POSITION, float3 normal : NORMAL, float4 color : COLOR)
{
v2f o;
o.color = color;
o.pos = UnityObjectToClipPos(vertex);
o.worldPos = mul(unity_ObjectToWorld, vertex).xyz;
o.worldNormal = UnityObjectToWorldNormal(normal);
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
float scale;
float _brightness;
float4 _SpecColor;
float _Shininess;
UNITY_DECLARE_TEX2DARRAY(_ArrTex);
fixed4 frag(v2f i) : SV_Target
{
////////////////////////////////// TRIPLANAR ////////////////////////////////
half texid = i.color.x * 255;
half3 norm = i.worldNormal;
// in wNorm is the world-space normal of the fragment
vector blending = abs(float4(norm.x, norm.y, norm.z, 0));
blending = normalize(max(blending, 0.00001)); // Force weights to sum to 1.0
float b = (blending.x + blending.y + blending.z);
blending /= vector(b, b, b, 1);
float4 xaxis = UNITY_SAMPLE_TEX2DARRAY(_ArrTex, float3(i.worldPos.y, i.worldPos.z, texid) * scale);
float4 yaxis = UNITY_SAMPLE_TEX2DARRAY(_ArrTex, float3(i.worldPos.x, i.worldPos.z, texid) * scale);
float4 zaxis = UNITY_SAMPLE_TEX2DARRAY(_ArrTex, float3(i.worldPos.x, i.worldPos.y, texid) * scale);
// in float scale
float4 tex = xaxis * blending.x + yaxis * blending.y + zaxis * blending.z;
tex = tex * _brightness;
////////////////////////////// LIGHTING ////////////////////////////////
float attenuation = LIGHT_ATTENUATION(i);
tex = tex * attenuation;
////////////////////////////////////////////////////////////////////////////////////
return tex;
}
ENDCG
}
Pass {
Blend one one
Tags { "LightMode" = "ForwardAdd" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include"UnityCG.cginc"
#pragma multi_compile_fwdadd_fullshadows
#include"AutoLight.cginc"
struct v2f
{
float3 worldPos : TEXCOORD0;
half3 worldNormal : TEXCOORD1;
float4 pos : SV_POSITION;
float4 color : COLOR;
LIGHTING_COORDS(2, 3)
};
v2f vert(appdata_base v, float4 vertex : POSITION, float3 normal : NORMAL, float4 color : COLOR)
{
v2f o;
o.color = color;
o.pos = UnityObjectToClipPos(vertex);
o.worldPos = mul(unity_ObjectToWorld, vertex).xyz;
o.worldNormal = UnityObjectToWorldNormal(normal);
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
float scale;
float _brightness;
float4 _SpecColor;
float _Shininess;
UNITY_DECLARE_TEX2DARRAY(_ArrTex);
fixed4 frag(v2f i) : SV_Target
{
////////////////////////////////// TRIPLANAR ////////////////////////////////
half texid = i.color.x * 255;
half3 norm = i.worldNormal;
// in wNorm is the world-space normal of the fragment
vector blending = abs(float4(norm.x, norm.y, norm.z, 0));
blending = normalize(max(blending, 0.00001)); // Force weights to sum to 1.0
float b = (blending.x + blending.y + blending.z);
blending /= vector(b, b, b, 1);
float4 xaxis = UNITY_SAMPLE_TEX2DARRAY(_ArrTex, float3(i.worldPos.y, i.worldPos.z, texid) * scale);
float4 yaxis = UNITY_SAMPLE_TEX2DARRAY(_ArrTex, float3(i.worldPos.x, i.worldPos.z, texid) * scale);
float4 zaxis = UNITY_SAMPLE_TEX2DARRAY(_ArrTex, float3(i.worldPos.x, i.worldPos.y, texid) * scale);
// in float scale
float4 tex = xaxis * blending.x + yaxis * blending.y + zaxis * blending.z;
tex = tex * _brightness;
////////////////////////////// LIGHTING ////////////////////////////////
float attenuation = LIGHT_ATTENUATION(i);
tex = tex * attenuation;
////////////////////////////////////////////////////////////////////////////////////
return tex;
}
ENDCG
}
}
Fallback"VertexLit"
}