Перенос функциональности трафарета OpenGL на DirectX 11

У меня есть некоторый код рендеринга, написанный на OpenGL. Я использую буфер трафарета для реализации отсечения:


//Let's assume this is done in render loop.

if(!already_created())
{
create_stencil_attachment_and_bind_to_FB_as_depth_stencil_attachment();
}

glEnable(GL_STENCIL_TEST);
glColorMask(0,0,0,0);
glDepthMask(0);
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS,1,1);
glStencilOp(GL_REPLACE,GL_REPLACE,GL_REPLACE);

render_to_stencil();

glColorMask(1,1,1,1);
glDepthMask(1);
glStencilFunc(GL_EQUAL,1,1);
glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);

render_with_clipping();

glDisable(GL_STENCIL_TEST);

Теперь проблема в том, что мне нужно перенести этот код на DX11. Я видел примеры на MSDN и некоторые хорошие учебники. Я в конечном итоге с этой логикой:

1. Создайте ID3D11Texture2D с форматом = DXGI_FORMAT_D32_FLOAT_S8X24_UINT.
2. Создайте ID3D11DepthStencilState для рендеринга в шаблон: // Давайте назовем его DS_RENDER
- Для передней и задней граней:
- op = D3D11_STENCIL_OP_REPLACE для всех 3 случаев
- func = D3D11_COMPARISON_ALWAYS
- DepthEnable = FALSE
- StencilEnable = TRUE
- StencilReadMask = 0xFF
- StencilWriteMask = 0xFF
3. Создайте ID3D11DepthStencilView для состояния и текстуры, созданных ранее. // Давайте назовем это DSV
4. Создайте ID3D11DepthStencilState для использования трафарета в качестве «ввода»: // Давайте назовем его DS_CLIP
- Для передней и задней граней:
- op = D3D11_STENCIL_OP_KEEP для всех 3 случаев
- func = D3D11_COMPARISON_EQUAL
- DepthEnable = FALSE
- StencilEnable = TRUE
- StencilReadMask = 0xFF
- StencilWriteMask = 0xFF

Теперь я не уверен, как установить трафарет в качестве цели или ввода.

MSDN говорит:

`pDevice->OMSetDepthStencilState(pDSState, 1);`

а также

`pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, pDSV);`

Если я правильно понимаю эти вызовы, первый устанавливает состояние трафарета, а второй связывает pDSV в качестве дополнительного «вложения» для отображения цели. Это верно?

Если так, будет ли это работать так, как я ожидаю?



pDevice->OMSetDepthStencilState(DS_RENDER, 1);
pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, DSV);

render_geometry_to_stencil_buffer();

pDevice->OMSetDepthStencilState(DS_CLIP, 1);

render_geometry_with_clipping();

pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, NULL); //Does this disable stencil testing?

Заранее спасибо за любую помощь или полезный совет.

4

Решение

Если вы хотите рендерить только трафарет, используйте (установка вашего состояния для записи):

pd3dDeviceContext->OMSetRenderTargets(0, NULL, DSV);

Вам не нужно делать рендеринг в цветной буфер, поэтому нет необходимости связывать его.

Затем для рендеринга к вашей цели и включения проверки трафарета используйте:

pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, DSV);

Когда вы используете трафарет в качестве входных данных, очень просто установить StencilWriteMask = 0;
Таким образом, он никогда не будет писать в него (это то, что вы хотите визуализировать обрезанную геометрию).

Если вы используете:

pd3dDeviceContext->OMSetRenderTargets(1, &pRTV, NULL);

Вы действительно отключите любую форму проверки глубины / трафарета (больше не ограничивает глубину, поэтому DepthStencilState не будет иметь никакого эффекта).

Также я бы использовал DXGI_FORMAT_D24_UNORM_S8_UINT для вашего формата глубины (личные предпочтения), он будет точно соответствовать вашему варианту использования и потреблять меньше памяти.

Надеюсь, это поможет.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]