I have started with a pixel shader that kills the color in every odd row of the texture and makes every second scanline transparent. If a black rectangle is overlaid with such a shaded image, each odd scanline will be seen as black, thus resulting in the desired black scanline effect.
An alternating line effect could be realized if an image instead of a black rectangle is overlaid.
After that I've extended the pixel shader to kill every odd pixel to produce the checkerboard effect William Moore wanted.
This is how a Silverlight Button could look like if the shader is applied to it:
How it works
The pixel shaders are pretty simple and small. As always, I've commented the HLSL code, but if you have any further questions, feel free to leave a comment.
Here is the shader that kills every odd scanline:
// Parameter float2 TextureSize : register(C0); // Sampler sampler2D TexSampler : register(S0); // Shader float4 main(float2 texCoord : TEXCOORD) : COLOR { // Default color is fully transparent float4 color = 0; // Scale to int texture size float row = texCoord.y * TextureSize.y * 0.5f; // Calc diff between rounded half and half to get 0 or 0.5 float diff = round(row) - row; float diffSq = diff * diff; // Even or odd? Only even lines are sampled if(diffSq < 0.1) { color = tex2D(TexSampler, texCoord); } return color; }
And here the shader that kills every odd pixel:
// Parameter float2 TextureSize : register(C0); // Sampler sampler2D TexSampler : register(S0); // Shader float4 main(float2 texCoord : TEXCOORD) : COLOR { // Default color is fully transparent float4 color = 0; // Scale to int texture size, add x and y float2 vpos = texCoord * TextureSize * 0.5f; float vposSum = vpos.x + vpos.y; // Calc diff between rounded half and half to get 0 or 0.5 float diff = round(vposSum) - vposSum; float diffSq = diff * diff; // Even or odd? Only even pixels are sampled if(diffSq < 0.1) { color = tex2D(TexSampler, texCoord); } return color; }
As you can see the only difference is that the kill pixel shader uses the sum of the texture coordinate's x and y component to determine if the pixel is even or odd.
For the effect of the uppermost blog post image (mandrill), I've used the product of x and y instead of the sum.
The size of the killed pixel group could be changed with the TextureSize parameter. The following example uses an eight of the original picture size as TextureSize.
Source code
I have also written a small Silverlight application that shows an image with the pixel shader attached. You can download the Visual Studio 2008 solution including the pixel shaders from here.
Photos from the USC-SIPI Image Database
Wow that's amazing I believed that you just can do that using photoshop or coreldraw, thanks for share, i will try.
ReplyDeletehello, i think that this post is very good beacause has useful information.
ReplyDeleteIn my Dither shader for SweetFX I needed an odd or even checkerboard pattern too.
ReplyDeleteI solved this with
float grid_position = frac(dot(tex,(screen_size / 2.0))+0.25); //returns 0.25 and 0.75
tex is my texcoords (a float2) and screen_size is a float2 with the size of the screen in pixels.
I need the +0.25 to avoid problems with imprecise floating point math.
It's extremely fast , compiles to only a DP2ADD and a FRC instruction.
If adapted to your shader it would look like this :
// Parameter
float2 TextureSize : register(C0);
// Sampler
sampler2D TexSampler : register(S0);
// Shader
float4 main(float2 texCoord : TEXCOORD) : COLOR
{
// Default color is fully transparent
float4 color = 0;
float diff = frac(dot(texCoord ,(TextureSize / 2.0))+0.25); //returns 0.25 and 0.75
// Even or odd? Only even pixels are sampled
if(diff < 0.5)
{
color = tex2D(TexSampler, texCoord);
}
return color;
}