Sign in to follow this  

storing two 16 bit floats in one 32 bit float (in HLSL)

This topic is 2847 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

is it possible? I am using directx 9.0 and as far as I know binary operations are not supported in dx9 I want to do something like that WORD x, y; DWORD z; z = x<<16 | y; but on HLSL and using floats. The reason is I want to store both color and normal of each pixel in a texture. I can do that using two textures but two rendering is very slow for me. Is there any other alternative for that?

Share this post


Link to post
Share on other sites

I ran into a similar issue recently and as far as I know, this is not supported. At least the FX compiler complained that << is an unexpected token. From my Googling, I learned that bitwise operators are only supported in SM4 and onwards.

You could use Spherical coordinates to store a 3 float normal and a 3 float color value in a A32R32G32B32F (or any narrower you can get away with) texture though. Since both the normal and color can be normalized, you can drop the r component for the spherical coordinate and just store the theta and phi for both values. This is actually easier than it may sound, so check out that link on how to do the conversions [smile]

The only downside here is that you end up with sin and cos operations in your shader, which may potentially be slower than sampling two textures. If you're constraint on the number of input textures and/or the number of samples you want to fetch however, it might be a feasible alternative.

Edit - Reading ET3D's reply below though, this is not quite the easiest nor best solution, so you probably shouldn't use it. It is a fancy one though [grin]

Share this post


Link to post
Share on other sites
First of all, how slow? I agree that one texture access is likely to be faster than two, since each has some latency, but I can't imagine that two memory accesses per pixel will be extremely costly. What graphics card are you using?

Regarding storing them together, it's not that difficult to simulate shifts and or's with multiplication and addition, and so on. You don't need floats for normals. Low accuracy can work pretty well for them in most cases, and you can either store two shorts or three 10 bit values inside a DWORD.

So a format such as D3DFMT_A16B16G16R16 could be good enough. Your values will be transformed to the 0-1 range, and to extract a colour components you can use one directly and the other as frac(component*255).

Share this post


Link to post
Share on other sites
remigius:
Thanks, I never thought about using spherical coordinates for color. I will try it and see how it works.

ET3D:
it is not the texture access I am worrying about. I need to do two rendering of the whole scene, one for colors and one for normals.

can you explain your suggestion a bit more? I am not sure if I get it right

Share this post


Link to post
Share on other sites
You don't need to render the scene twice. What you can do is use multiple simultaneous render targets (MRT) to write to two render targets at the same time. This is often used in deferred shading.

Your code would look something like:


device->SetRenderTarget(0, colour_buffer);
device->SetRenderTarget(1, normal_buffer);
// Draw stuff with shader that outputs to both targets


Note that depending on your hardware both targets may need to be the same bit depth, but they can be different formats (e.g. one R32F and one D3DFMT_A2R10B10G10 is fine).

Share this post


Link to post
Share on other sites
Quote:
Original post by Adam_42
You don't need to render the scene twice. What you can do is use multiple simultaneous render targets (MRT) to write to two render targets at the same time. This is often used in deferred shading.

Your code would look something like:


device->SetRenderTarget(0, colour_buffer);
device->SetRenderTarget(1, normal_buffer);
// Draw stuff with shader that outputs to both targets


Note that depending on your hardware both targets may need to be the same bit depth, but they can be different formats (e.g. one R32F and one D3DFMT_A2R10B10G10 is fine).


Oh, I didn't know about that, thanks! But how should I configure my pixel shader for drawing on two targets?


float4 PS_COOR( in V2P4 IN) : COLOR0{
float4 TexColor = float4(IN.Norm.xyz, 1.0);
return TexColor;
}


so I guess COLOR0 means render target 0, can a shader return more than 1 value or do I need seperate shader for each render targer. if so how should I configure my technique

Share this post


Link to post
Share on other sites

You can just stick the seperate values in a struct and the device will know what to do with the semantics. Something like this:


struct PSOutput
{
float4 color : COLOR0; // to RT0
float4 normals : COLOR1; // to RT1
};

PSOutput PS_COOR( in V2P4 IN) {
PSOutput output;
output.color = float4(IN.Norm.xyz, 1.0);
output.normals = float4(0,0,0,0);// whatever you need
return output;
}

Btw, I second the request to ET3D to elaborate on his suggestion. I Googled quite a bit, but I couldn't find any code that could reliably do back and forth bitwise operations. I was specifically looking for something to transform a float into 4 bytes and back again, if you happen to need a simple case to explain [smile]

Share this post


Link to post
Share on other sites
You just need to write to COLOR0, and COLOR1 from one shader, something like:


struct PS_OUT
{
float4 colour : COLOR0;
float4 normal : COLOR1;
};

PS_OUT PS_COOR( in V2P4 IN)
{
PS_OUT out;

// TODO: fill in out

return out;
}

Share this post


Link to post
Share on other sites
sorry, another question about multiple render targets.

should I call SetRenderTarget methods before beginScene? and D3Ddev->clear() clears all render targets or can I clear a specific render target?

edit: I figured to problem. thanks anyway

[Edited by - shultays on February 25, 2010 1:18:39 PM]

Share this post


Link to post
Share on other sites

This topic is 2847 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this