I’m creating a simple outline shader to render on sprites in a spritesheet. I’m sampling the color of the current pixel and all neighboring pixels to decide whether to apply the outline color or not.
Here’s my shader:
#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0_level_9_3
#define PS_SHADERMODEL ps_4_0_level_9_3
#endif
struct VertexShaderOutput
{
float4 Position : SV_POSITION;
float4 Color : COLOR0;
float2 TextureCoordinates : TEXCOORD0;
};
sampler s0 = sampler_state { AddressU = Clamp; AddressV = Clamp; };
float2 texelSize;
float4 outlineColor;
float4 Outline(VertexShaderOutput input) : COLOR
{
float4 color = tex2D(s0, input.TextureCoordinates);
if (color.a == 0)
{
float4 colorUp = tex2D(s0, input.TextureCoordinates - float2(0, texelSize.y));
float4 colorDown = tex2D(s0, input.TextureCoordinates + float2(0, texelSize.y));
float4 colorLeft = tex2D(s0, input.TextureCoordinates - float2(texelSize.x, 0));
float4 colorRight = tex2D(s0, input.TextureCoordinates + float2(texelSize.x, 0));
if (colorUp.a != 0 || colorDown.a != 0 || colorLeft.a != 0 || colorRight.a != 0)
{
color.rgba = outlineColor;
}
}
return color;
}
technique BasicColorDrawing
{
pass P0
{
PixelShader = compile PS_SHADERMODEL Outline();
}
};
I stepped through the logic manually with pencil and paper, but I couldn’t find any errors. I suspect that the texelSize parameter is incorrect; this is what I pass into the shader:
Vector2 texelSize = new Vector2((float)(1 / (double)playerSprite.Tex.Width), (float)(1 / (double)playerSprite.Tex.Height));
My spritesheet is 764x1358, so the values come out to 0.00130890052356020942408376963351 and .00073637702503681885125184094256259 before they’re converted to floats. After conversion, they come out to 0.001308901 and 0.000736377 respectively, which is a huge loss in accuracy. I tried enlarging my spritesheet with empty space to make it 1024x2056, and while this produced overall better results after the float conversion, there were still some inaccuracies. I suspect that these inaccuracies are causing my outline to be offset up and to the left by a pixel.
I also tried passing in the texture dimensions and calculating the single pixel texture coordinate from within the shader, but that produced the same results.
Is there a way to get texture coordinate values that correspond exactly to one pixel for larger textures?