Problem getting correct total gathered light of an hemicube with GPU

Started by
2 comments, last by Koder4Fun 14 years, 3 months ago
I have a problem to get the total light gathered from an hemicube using the GPU (the CPU algorithm work well so i know that the problem is the correct sampling of the source texture into the render target). I already have readed some documents like "map pixels to texels" of Microsoft and others for post-processing and it's works for textures of the same size of the render target (for example deferred shading, blurring, HDR, etc...). To gather light my idea is to do a 16 tap sampling forming a 4x4 square of pixel that are summed inside a pixel shader and rendered to a target. Using hemicube edge size that are power of 4 i can recursively downsample to the 3x1 target (all views are packed inside one texture) but the value is not the same of the CPU version and lightmaps are incorrect. This is the packed hemicube texture, it's contains left, front, right, top and bottom views: Free Image Hosting at www.ImageShack.us This is the code of the vertex and pixel shaders used:

struct VS_OUTPUT
{
   float4 pos       : POSITION0;
   float2 texCoord  : TEXCOORD0;
};

const float2 sourceSize = float2(48, 16);
const float2 viewportSize = float2(48, 16) * 0.25;

VS_OUTPUT vs_main(float4 inPos: POSITION )
{
   VS_OUTPUT o = (VS_OUTPUT) 0;

   inPos.xy = sign(inPos.xy);
   o.pos = float4(inPos.xy, 0.0f, 1.0f);
   //o.pos.xy += float2(-1, 1) / viewportSize;
   //if (o.pos.x == 1.0) o.pos.x -= 0.5 / viewportSize;
   //if (o.pos.y == 1.0) o.pos.x -= 0.5 / viewportSize;

   // get into range [0,1]
   o.texCoord = float2(0.5, -0.5) * inPos.xy + 0.5;
   //o.texCoord += 0.5 / viewportSize;
   o.texCoord *= sourceSize;

   return o;
}

const float2 sampleOffsets[16] =
{
	{0.0, 0.0}, {1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0},
	{0.0, 1.0}, {1.0, 1.0}, {2.0, 1.0}, {3.0, 1.0},
	{0.0, 2.0}, {1.0, 2.0}, {2.0, 2.0}, {3.0, 2.0},
	{0.0, 3.0}, {1.0, 3.0}, {2.0, 3.0}, {3.0, 3.0},
};

float4 ps_main( float2 texCoord  : TEXCOORD0 ) : COLOR
{
	float4 color = 0.0;
	//float2 s = sourceSize / (sourceSize - 1);
	for (int i = 0; i < 16; i++)
	{
		float2 uv = (texCoord + sampleOffsets) / sourceSize;
		color += tex2D(diffuseTex, uv);
	}
	
	return color;
}


as you can see I've made some tests on texel and vertex coordinate adjustement. This implementation on a test texture show the incorrect sampling below becose the 4x4 dark boxes must rest black: Image Hosted by ImageShack.us Note: this image is a 12x4 target (zoomed) sampled from 48x16 texture. Can anyone help me please. All replies are wellcome.
Please vote usefull replies.
Marco Sacchi
Coding is a challenge ... but solving problems is the fun part
My Blog - XNA Italian portal
Advertisement
I think you forgot to multiply texCoord by float2(4,4), since that's how many source pixels each destination pixel covers

There's possibly other stuff wrong too, but that should be a start

Also, you should ensure you're doing point sampling on the texture to ensure there's no filtering being done by the gpu
You might also need to multiply texCoord by sourceSize since you're expressing most stuff in whole integer pixel coordinates, but that value interpolates from 0 to 1

You should do another test with a test texture and just sample the top-left pixel of each 4x4 block and write it to the destination - that might help you find more fundamental bugs and make sure you've even got that part right
Thankyou for the tips RDragon1 i check and i back if i need more infos.

I think disabling the filtering is not a solution because if I sample the texel on the right coordinate (texel's center) I get the same result.

With se POINT sampling with error accumulation in sampling I can sample another than the right texel.
Please vote usefull replies.
Marco Sacchi
Coding is a challenge ... but solving problems is the fun part
My Blog - XNA Italian portal

This topic is closed to new replies.

Advertisement