0
\$\begingroup\$

I am trying to implement object picking via a shaders. My intent is to create a texture2d that I would write out ID values describing individual objects.

Following drawing the objects, I would query back the pixel value at the focus point and read out the ID of the object.

I've created my texture2d as follows:

// Create a very tiny selection texture.
// This will record the color ID as unique identifier of a selectable object.
D3D11_TEXTURE2D_DESC desc;
desc.Width = 1;
desc.Height = 1;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R32_UINT;  // 16 bit integer, hold up to 65536 possible unique IDs.
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_STAGING; // We will write via GPU and read to CPU!
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.MiscFlags = 0;

HRESULT result = m_deviceResources->GetD3DDevice()->CreateTexture2D(&desc, 0, &m_colorRenderTarget);
if (FAILED(result)) {
    OutputDebugString(L"PickRenderer: Unable to create Texture2D");
}

Is it possible to then to make a pixel shader that would write out an R32 integer value, rather than the float values for RGBA? If so, how would I best do this?

My pixel shader currently writes float RGB values out as follows:

// A constant buffer that stores the model transform.
cbuffer ModelConstantBuffer : register(b0)
{
    float4x4    modelToWorld;
    float3      color;  // Instead use unsigned int32 here if possible?
};

// Per-vertex data used as input to the vertex shader.
struct PixelShaderInput
{
    min16float4 pos     : POSITION;
};

// Can this use a different return value for uint?
min16float4 main(PixelShaderInput IN) : SV_TARGET
{
    return min16float4(color, 1.f);
}

Thanks, I've been trying to find an answer to this, but it seems very unusual to write out non-float values if it is possible.

\$\endgroup\$
1
\$\begingroup\$

I use a uint texture to store material ID's.

The shader output struct I use for this is and the ID constant:

uint matID;

struct PixelShaderOutput
{          
 uint RenderMaterialID : SV_Target0;   
};

Write to the output targets:

PixelShaderOutput PShader(PixelShaderInput input)
{
 PixelShaderOutput output = (PixelShaderOutput) 0;   
 output.RenderMaterialID = matID;  

 return output;
}

Then just read back the ID texture at a later stage in your render pipeline

Texture2D<uint> RenderMaterialIDs;
uint MatID = RenderMaterialIDs.Load(uint3(globalIdx.x, globalIdx.y, 0));
\$\endgroup\$
0
\$\begingroup\$

Pixel Shaders output float values that are converted to the appropriate format as they are placed into the Render Target. If you look at Direct3D feature levels, some feature levels support a UINT or SINT format for a render target. So if you returned 255.0, it would write 255 into the UINT render target.

Otherwise you need to use DirectCompute.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.