Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A function like "glReadPixels" in DirectX / SharpDX

I'm searching for a way to read a pixels color at the mousepoint. In OpenGL it was done by calling the function "glReadPixels" after drawing the scene (or parts of it). I want to make a simple color picking routine in the background, for identifing a shapes / lines in 3D Space.

So, is there any equivalent method/function/suggestion for doing the same in SharpDX (DirectX10 / DirectX11) ?

like image 639
lunatix Avatar asked Nov 12 '12 11:11

lunatix


3 Answers

This is perfectly possible with Direct3D11: simply follow these steps:

  • Use DeviceContext.CopySubResourceRegion to copy part from the source texture to a staging texture (size of the pixel area you want to readback, same format, but with ResourceUsage.Staging)
  • Retrieve the pixel from this staging texture using Device.Map/UnMap.

There is plenty of discussion about this topic around the net (for example: "Reading one pixel from texture to CPU in DX11")

like image 54
xoofx Avatar answered Oct 13 '22 11:10

xoofx


Another option is to use a small compute shader, like :

Texture2D<float4> TextureInput: register(t0);
StructuredBuffer<float2> UVBuffer: register(t1);
RWStructuredBuffer<float4> RWColorBuffer : register(u0);

SamplerState Sampler : register( s0 );

[numthreads(1, 1, 1)]
void CSGetPixels( uint3 DTid : SV_DispatchThreadID )
{ 
float4 c = TextureInput.SampleLevel(Sampler , UVBuffer[DTid.x].xy, 0);
RWColorBuffer [DTid.x] = c;
}

It gives you the advantage of being a bit more "format agnostic".

Process is then like that.

  • Create a small structured buffer for UV (float2) (pixel position/texture size, don't forget to flip Y axis of course). Copy the pixel position you want to sample into this buffer.
  • Create a writeable buffer and a staging buffer (float4). Needs to be same element count as your uv buffer.
  • Bind all and Dispatch
  • Copy writeable buffer into the staging one.
  • Map and read float4 data in cpu

Please note I omitted thread group optimization/checks in compute shader for simplicity.

like image 21
mrvux Avatar answered Oct 13 '22 13:10

mrvux


Since you're using C#, my suggestion would be to use GDI+, as there is no such function like "glReadPixels" in DX. GDI+ offers very easy methods of reading the color of a pixel at your mouse pointer. Refer to stackoverflow.com/questions/1483928.

If GDI+ is a no go, as it isn't very fast, can't you stick to the usual object picking using a "Ray"? You want to identify (I suppose 3-dimensional) shapes/lines, this would be easy using a ray (and check for intersection) to pick them.

like image 1
KeyNone Avatar answered Oct 13 '22 13:10

KeyNone