In the quest to fix seam lighting with normal maps, I found Ryan Brucks had done an apparently really effective solution, but my port of that is bugged.
Can you cast your eyes over this and spot where the problem might be? I’m getting white spots and a generally bad result and it’s probably something I missed when porting.
Original Code:
//////////////// UV Positional Dilation ///////////////////////////
//** Tex **// Input Texture Object storing Volume Data
//** UV **// Input float2 for UVs
//** TextureSize **// Resolution of render target
//** MaxSteps **// Pixel Radius to search
float texelsize = 1 / TextureSize;
float mindist = 10000000;
float2 offsets[8] = {float2(-1,0), float2(1,0), float2(0,1), float2(0,-1), float2(-1,1), float2(1,1), float2(1,-1), float2(-1,-1)};
float3 sample = Tex.SampleLevel(TexSampler, UV, 0);
float3 curminsample = sample;
if(sample.x == 0 && sample.y == 0 && sample.z == 0)
{
int i = 0;
while(i < MaxSteps)
{
i++;
int j = 0;
while (j < 8)
{
float2 curUV = UV + offsets[j] * texelsize * i;
float3 offsetsample = Tex.SampleLevel(TexSampler, curUV, 0);
if(offsetsample.x != 0 || offsetsample.y != 0 || offsetsample.z != 0)
{
float curdist = length(UV - curUV);
if (curdist < mindist)
{
float2 projectUV = curUV + offsets[j] * texelsize * i * 0.25;
float3 direction = Tex.SampleLevel(TexSampler, projectUV, 0);
mindist = curdist;
if(direction.x != 0 || direction.y != 0 || direction.z != 0)
{
float3 delta = offsetsample - direction;
curminsample = offsetsample + delta * 4
}
else
{
curminsample = offsetsample;
}
}
}
j++;
}
}
}
return curminsample;
My port:
Shader "Internal/Dilate"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float _TexelSize;
int _MaxSteps;
float3 Sample(float2 uv, float lod)
{
return tex2Dlod(_MainTex, float4(uv, 0, lod)).rgb;
}
float3 SimpleDilate(float2 uv)
{
float2 offsets[8] = { float2(-1,0), float2(1,0), float2(0,1), float2(0,-1), float2(-1,1), float2(1,1), float2(1,-1), float2(-1,-1) };
float minDist = 10000000;
float3 samp = Sample(uv, 0);
float3 currentMinSample = samp;
if (samp.x == 0 && samp.y == 0 && samp.z == 0)
{
int i = 0;
while (i < _MaxSteps)
{
i++;
int j = 0;
while (j < 8)
{
float2 offsetUV = uv + offsets[j] * _TexelSize * i;
float3 offsetSample = Sample(offsetUV, 0);
if (offsetSample.x != 0 || offsetSample.y != 0 || offsetSample.z != 0)
{
float dist = length(uv - offsetUV);
if (dist <= minDist)
{
minDist = dist;
float2 extrapolatedUV = offsetUV + offsets[j] *_TexelSize * i * 0.25;
float3 direction = Sample(extrapolatedUV, 0);
if (direction.x != 0 || direction.y != 0 || direction.z != 0)
{
float3 delta = offsetSample - direction;
currentMinSample = offsetSample + delta * 4;
}
else
{
currentMinSample = offsetSample;
}
}
}
j++;
}
}
}
return currentMinSample;
}
v2f vert (appdata v)
{
v2f o;
o.uv = v.uv;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
float4 frag(v2f i) : SV_Target
{
return float4(SimpleDilate(i.uv), 1);
}
ENDCG
}
}
}
Original article and explanation:
Thanks for any insights ![]()


