Some strange problem with a pixel shader.

Recommended Posts

Hi to all. I've, some day ago, implemented the bloom effect to my game. To do this, i've taken the "post-process" demo of the directx sdk and used it's tecnique to make the illumination. It works very well, but it has some strange behaviour near the border of the screen. To simplify all the chain, i've left only one shader, applied twice to the scene. It makes an high filtering on the image and downsize it by 4 times. So at the end i've the image resized by 16 times. It works but.. try to look at these two screenshot: The pixel in evidence has two colours, very similar but not the same. Usually, when a pixel reach the border, it's colour is more brighter, and it's a simple resize shader, there's no light computation, colour computation and so on. I'm surprised, all the pixels should maintains the same colour when it scrolls on the screen. It's very difficult to debug the shader because i don't render the result on the back screen, but into a texture, then i use the texture and apply to a quad (-1,-1)-(1,1) with uv coords (0,0)-(1,1), and i'm not very skilled to use pix (i've tried the example of SDK but when i activate the debug_vs and debug_ps the rendering is about 0.01 FPS and it's impossible to do anything). Anyway this is the shader i've used:


// by pdg

uniform extern texture gTex;
uniform extern float gSizeh;
uniform extern float gSizev;

sampler2D g_samSrcColor =
sampler_state
{
Texture = <gTex>;
MinFilter = Point;
MagFilter = Point;
MipFilter = Point;
};

float2 PixelCoordsDownFilter[16] =
{
{ 1.5,  -1.5 },
{ 1.5,  -0.5 },
{ 1.5,   0.5 },
{ 1.5,   1.5 },

{ 0.5,  -1.5 },
{ 0.5,  -0.5 },
{ 0.5,   0.5 },
{ 0.5,   1.5 },

{-0.5,  -1.5 },
{-0.5,  -0.5 },
{-0.5,   0.5 },
{-0.5,   1.5 },

{-1.5,  -1.5 },
{-1.5,  -0.5 },
{-1.5,   0.5 },
{-1.5,   1.5 },
};

float2 TexelCoordsDownFilter[16]
<
string ConvertPixelsToTexels = "PixelCoordsDownFilter";
>;

struct OutputVS
{
float4 posH    : POSITION0;
float2 tex0    : TEXCOORD0;
};

OutputVS DownVS(float3 posL : POSITION0, float2 tex0 : TEXCOORD0)
{
// Zero out our output.
OutputVS outVS = (OutputVS)0;

// Position already in normalized device coordinates.
outVS.posH = float4(posL, 1.0f);

// Pass on texture coordinates to be interpolated in rasterization.
outVS.tex0 = tex0;

// Done--return the output.
return outVS;
}

float4 DownPS(in float2 tex0 : TEXCOORD0) : COLOR
{
float4 Color = 0;

for (int i = 0; i < 16; i++)
{
Color += tex2D( g_samSrcColor,tex0 + PixelCoordsDownFilter[i].xy/float2(gSizeh,gSizev) );
}

return Color / 16;

}

technique DownTech
{
pass p0
{
ZEnable = false;
}
}


The shader takes each pixel, and compute it's colour as "average" of the pixel around it. The PixelCoordsDownFilter[i].xy/float2(gSizeh,gSizev) operation needs to normalize the pixel space from (0,0)-(width,height) to (0,0)-(1,1) Any good idea? If you need some information i'll happy to give you. Thank you

Share on other sites
You get this result because you have used a centered box filter to downsample the image, and the texture address on the state_sampler is set to CLAMP.

When you average the texels near one or more edges, you sample more times the same texel due to the clamp of texture coordinate in the range [0...1].

You can ignore this artifact, it's almost invisible.

Share on other sites
For bloom you don't want to use a point filter anyway for your downscaling and upscaling, otherwise you get that terrible pixelated look. You'll either want to use linear filtering, or if a GPU doesn't support linear filtering then emulate linear filtering in the shader.

Also if you want to debug pixel shaders or look at render targets in PIX, all you need to do is run it in the mode that lets you capture frames with F12. Then you just capture a single frame, find the texture you rendered to in the list of textures, and then you can view and debug pixels.

Share on other sites
Quote:
 Original post by Koder4FunYou get this result because you have used a centered box filter to downsample the image, and the texture address on the state_sampler is set to CLAMP.When you average the texels near one or more edges, you sample more times the same texel due to the clamp of texture coordinate in the range [0...1].You can ignore this artifact, it's almost invisible.

unfortunatelly this is only the first step.
the others are one pass of bright filter, 4 passes of horrizontally and vertically bloom, a scaling of 4x and a final pass that combine the results.
The artifact that you see on the screenshot are not so noticeable.
But after a bright pass and 4 bloom passes, it's very evident.
And on the sdk demo it does not make the same artifact, using the same shader. I wonder why...

Share on other sites
Quote:
 Original post by MJPFor bloom you don't want to use a point filter anyway for your downscaling and upscaling, otherwise you get that terrible pixelated look. You'll either want to use linear filtering, or if a GPU doesn't support linear filtering then emulate linear filtering in the shader.Also if you want to debug pixel shaders or look at render targets in PIX, all you need to do is run it in the mode that lets you capture frames with F12. Then you just capture a single frame, find the texture you rendered to in the list of textures, and then you can view and debug pixels.

yes i've used linear interpolation: i've forced point here for debugging.

For debugging the question is: how i should do to make a step-by-step debug of a shader with his hlsl source (and not in assembly)?
I've tried to follow the pix project included inside the directx sdk but when i uncomment the two lines to enable the debugging, the shaders is emulated by cpu and the program runs about 1000 time slower, and it's impossible also to press F12...

Share on other sites
Quote:
 Original post by PdGFor debugging the question is: how i should do to make a step-by-step debug of a shader with his hlsl source (and not in assembly)?I've tried to follow the pix project included inside the directx sdk but when i uncomment the two lines to enable the debugging, the shaders is emulated by cpu and the program runs about 1000 time slower, and it's impossible also to press F12...

You don't need to #define anything in your code. All you need to do is enable debugging info when you compile your shaders. If you're compiling them in your app using D3DXCreateEffectFromFile or D3DXCompileShaderFromFile then you need to pass D3DXSHADER_DEBUG as one of the flags. Or if you're using fxc to compile offline, use the /Zi switch. Doing this will embed the name of the source .fx file, which will allow PIX to link the shader back to your HLSL source.

You may also want to disable optimizations when you compile, since otherwise your instructions won't execute in the order you wrote them. However keep in mind this might cause you to exceed the instruction limit or register limits of lower shader profiles.

Share on other sites
Ok, found the problem, not the solution.

The filter takes all the pixel around the current point.
If the pixel is on the border, i.e. left, at left there's nothing and the average give a value below than the value gave when the pixel is at the center.
The same problem i've when i blend a pixel to obtain the bloom effect... the effect is obtained after a eight-pass chain, so the error is amplified obtaining the strange effect that i've (is MORE visible than the screenshot of my previous post).
For now i've found only this solution: the quad that i use to display the scene should be scaled a bit so the border are out of screen, and the artifacts are not visible.

Any other ideas?

Create an account

Register a new account

• Forum Statistics

• Total Topics
628400
• Total Posts
2982449

• 9
• 10
• 9
• 19
• 24