G16R16 readback woes

Started by
3 comments, last by edwinnie 18 years, 1 month ago
hi there! After being successful at G16R16F readbacks using the D3DXFloat16To32Array conversion functionality, I decided to try on a non-floating point one. So far I arrived at the code below without using the D3DXFloat16To32Array currently. I am having problems trying to convert a WORD to a float with respect to G16R16. I hope there is someone who can help me. thx! Edwin

//sample code is not correct
if(format == D3DFMT_G16R16)
{
	for(int y=0; y<desc.Height; y++)
	{
		WORD* pPixel = (WORD*)(((BYTE*)theRect.pBits) +(y*theRect.Pitch));
		for(int x=0; x<desc.Width; x++)
		{
			WORD red = (*pPixel&0xffff0000)>>16; //wrong!
			WORD green = (*pPixel&0xffff);       //wrong!
			pPixel++;
							
			int index = (y * desc.Width + x) * compSize;
			(*data)[index] = red / 65535;
			(*data)[index+1] = green / 65535;
		}
	}
}


Advertisement
By using a WORD pointer you're going to be addressing per channel of each pixel - you'd need to use a DWORD (or UINT32) to step along each pixel.

You could try using a D3DXFLOAT16 pointer to step along per-channel. The extensions for that class should allow easier manipulation of the values (to or from regular float variables).

The other thing - your red / 65535 part looks suspect. That'll just give you a 0 or 1 in the WORD if I'm thinking straight [grin]. WORD's are still integer quantities, and your division (at a guess) will result in a 0.0 to 1.0 value - and you want the full decimal resolution. Assigning it to an integer quantity will give you rounding and you'll end up with either 0 or 1.

Also related to that, unless you're using D3DXFLOAT16 it won't know how to store it in proper s1e5m10 format. For regular float it knows how to convert something like 3.14159 into IEEE754, but that's not the case here.

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

hi jack!

ok i remember using D3DXFLOAT16 and managed to get part of the intermediate results correct. I had a pixelshader which outputs half4(0.25,0.5,0,0) into the surface with G16R16 format. If I try to acquire the values using D3DXFLOAT16 and access them via the pointer, I can get 16384 and 32768 nicely (both have datatype D3DXFLOAT16 though).

Now I need to convert the D3DXFLOAT16 to a proper 32bit float. But I cannot seem to do it directly using D3DXFloat16To32Array. The very first 'red' and 'green' values gave '2.0' and '0.0' which did not match the output from the pixelshader.

hope u can enlighten this matter further.
thx!
Edwin

for(int y=0; y<desc.Height; y++){	D3DXFLOAT16* pPixel16 = (D3DXFLOAT16*)(((BYTE*)theRect.pBits) + (y*theRect.Pitch));							int count = desc.Width * compSize;//compSize == 2	float* pPixel32 = new float[count];	D3DXFloat16To32Array(pPixel32,pPixel16,count);							for(int x=0; x<desc.Width; x++) 	{		int texelID = x * compSize;		float red = pPixel32[texelID];		float green = pPixel32[texelID+1];                //...	        }	//...}
I missed it earlier, but there is a casting operator defined for D3DXFLOAT16:

D3DXFLOAT16 pi( 3.14159f );
float fPi = static_cast< float >( pi );

When outputted:

fPi = 3.140625 (raw: 16968)

It's not precise, but that's to be expected from a half precision float [smile]

With that in mind, you should be able to step through each pixel and convert it to a float, and if you want to go from a float to a D3DXFLOAT16 you can use the constructor (example above)...

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

hi jack!
thx fer replying!

unfortunately i realized something weird. Initially i outputted half4(0.25,0.5,0,0) from the pixelshader. But if i do this:

D3DXFLOAT16 pi( 0.25 );
float fPi = static_cast< float >( pi );

'pi' is of value '13312'. This means that the first element of the D3DXFLOAT16* did not return the correct value. Although the value reads as '16384', which is 0.25 of 65536, it should read as '13312' in order to get the '0.25' back.

I wonder if i am missing a few more things...

thx again!
Edwin

This topic is closed to new replies.

Advertisement