Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Esta seção aborda as etapas para configurar o buffer de estêncil de profundidade e o estado de estêncil de profundidade para o estágio de fusão de saída.
- Criar um recurso de Depth-Stencil
- Criar estado de Depth-Stencil
- Associar dados Depth-Stencil ao estágio de OM
Depois de saber como usar o buffer de estêncil de profundidade e o estado correspondente de estêncil de profundidade, consulte técnicas de estêncil avançado.
Criar um recurso Depth-Stencil
Crie o buffer de estêncil de profundidade usando um recurso de textura.
ID3D11Texture2D* pDepthStencil = NULL;
D3D11_TEXTURE2D_DESC descDepth;
descDepth.Width = backBufferSurfaceDesc.Width;
descDepth.Height = backBufferSurfaceDesc.Height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = pDeviceSettings->d3d11.AutoDepthStencilFormat;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
hr = pd3dDevice->CreateTexture2D( &descDepth, NULL, &pDepthStencil );
Criar estado de Depth-Stencil
O estado de estêncil de profundidade informa ao estágio de fusão de saída como executar o teste de estêncil de profundidade . O teste de estêncil de profundidade determina se um determinado pixel deve ou não ser desenhado.
D3D11_DEPTH_STENCIL_DESC dsDesc;
// Depth test parameters
dsDesc.DepthEnable = true;
dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
dsDesc.DepthFunc = D3D11_COMPARISON_LESS;
// Stencil test parameters
dsDesc.StencilEnable = true;
dsDesc.StencilReadMask = 0xFF;
dsDesc.StencilWriteMask = 0xFF;
// Stencil operations if pixel is front-facing
dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Stencil operations if pixel is back-facing
dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Create depth stencil state
ID3D11DepthStencilState * pDSState;
pd3dDevice->CreateDepthStencilState(&dsDesc, &pDSState);
DepthEnable e StencilEnable habilitam (e desabilitam) o teste de profundidade e o teste de estêncil. Defina DepthEnable como FALSE para desabilitar o teste de profundidade e impedir a gravação no buffer de profundidade. Defina StencilEnable como FALSE para desabilitar o teste de estêncil e impedir a gravação no buffer de estêncil (quando DepthEnable for FALSE e StencilEnable for TRUE, o teste de profundidade sempre será aprovado na operação de estêncil).
DepthEnable afeta apenas o estágio de fusão de saída - ele não afeta o recorte, o deslocamento de profundidade ou a limitação de valores antes que os dados sejam inseridos em um pixel shader.
Associar dados Depth-Stencil ao estágio de OM
Associe o estado de estêncil de profundidade.
// Bind depth stencil state
pDevice->OMSetDepthStencilState(pDSState, 1);
Associe o recurso de estêncil de profundidade usando uma exibição.
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
descDSV.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
// Create the depth stencil view
ID3D11DepthStencilView* pDSV;
hr = pd3dDevice->CreateDepthStencilView( pDepthStencil, // Depth stencil texture
&descDSV, // Depth stencil desc
&pDSV ); // [out] Depth stencil view
// Bind the depth stencil view
pd3dDeviceContext->OMSetRenderTargets( 1, // One rendertarget view
&pRTV, // Render target view, created earlier
pDSV ); // Depth stencil view for the render target
Uma matriz de visualizações de alvo de renderização pode ser passada para ID3D11DeviceContext::OMSetRenderTargets, no entanto, todas essas visualizações de alvo de renderização estarão associadas a uma única exibição de estêncil de profundidade. A matriz de destino de renderização no Direct3D 11 é um recurso que permite que um aplicativo seja renderizado em vários destinos de renderização simultaneamente no nível primitivo. As matrizes de destino de renderização oferecem maior desempenho em relação à configuração individual de destinos de renderização com várias chamadas para ID3D11DeviceContext::OMSetRenderTargets (essencialmente o método empregado no Direct3D 9).
Os destinos de renderização devem ser todos do mesmo tipo de recurso. Se o antisserrilhamento multiamostra for usado, todos os alvos de renderização associados e buffers de profundidade deverão ter as mesmas contagens de amostras.
Quando um buffer é usado como um destino de renderização, não há suporte para testes de estêncil de profundidade e vários destinos de renderização.
- Até 8 alvos de renderização podem ser associados simultaneamente.
- Todos os destinos de renderização devem ter o mesmo tamanho em todas as dimensões (largura, altura e, no caso de renderizações 3D, profundidade, ou tamanho de array para tipos de Array).
- Cada destino de renderização pode ter um formato de dados diferente.
- As máscaras de escrita controlam quais dados são gravados em um alvo de renderização. As máscaras de gravação de saída controlam em nível de destino de renderização e de componente quais dados são gravados nos destinos de renderização.
Técnicas avançadas de estêncil
A parte do estêncil do buffer de estêncil de profundidade pode ser usada para criar efeitos de renderização, como compositing, decalque e delineamento.
- Composição
- de decalque
- Contornos e Silhuetas
- Estêncil Two-Sided
- Lendo o Buffer Depth-Stencil como uma Textura
Composição
Seu aplicativo pode usar o buffer de estêncil para integrar imagens 2D ou 3D em uma cena 3D. Uma máscara no buffer de estêncil é usada para ocultar uma área da superfície alvo de renderização. Informações 2D armazenadas, como texto ou bitmaps, podem ser escritas na área ocluída. Como alternativa, seu aplicativo pode renderizar primitivos 3D adicionais na região mascarada por estêncil da superfície de destino de renderização. Ele pode até renderizar uma cena inteira.
Os jogos geralmente compõem várias cenas 3D juntas. Por exemplo, os jogos de condução normalmente exibem um espelho retrovisor. O espelho contém a visão da cena 3D atrás do motorista. É essencialmente uma segunda cena 3D combinada com a visão frontal do motorista.
Decalque
Os aplicativos Direct3D usam o decalque para controlar quais pixels de uma imagem primitiva específica são desenhados para a superfície de destino de renderização. Os aplicativos aplicam decalques às imagens de primitivos para permitir que polígonos coplanares sejam renderizados corretamente.
Por exemplo, ao aplicar marcas de pneus e linhas amarelas a uma estrada, as marcas devem aparecer diretamente no topo da estrada. No entanto, os valores z das marcações e da estrada são os mesmos. Portanto, o buffer de profundidade pode não produzir uma separação limpa entre os dois. Alguns pixels na primitiva de fundo podem ser renderizados sobre a primitiva de frente e vice-versa. A imagem resultante parece cintilar de quadro em quadro. Esse efeito é chamado de Z-Fighting ou Flimmering.
Para resolver esse problema, use um estêncil para mascarar a seção do primitivo de fundo em que o decalque será exibido. Desative o buffer z e renderize a imagem do primitivo frontal na área mascarada da superfície de destino de renderização.
A combinação de várias texturas pode ser usada para resolver esse problema.
Contornos e silhuetas
Você pode usar o buffer de estêncil para efeitos mais abstratos, como contornos e silhuetas.
Se o aplicativo executar duas passagens de renderização - uma para gerar a máscara de estêncil e a segunda para aplicar a máscara de estêncil à imagem, mas com as primitivas ligeiramente menores na segunda passagem - a imagem resultante conterá apenas o contorno do primitivo. Em seguida, o aplicativo pode preencher a área da imagem mascarada pelo estêncil com uma cor sólida, conferindo ao primitivo uma aparência relevada.
Se a máscara de estêncil tiver o mesmo tamanho e forma que a primitiva que você está renderizando, a imagem resultante conterá um buraco onde o primitivo deve estar. Seu aplicativo pode então preencher a lacuna com preto para produzir uma silhueta do primitivo.
Estêncil Two-Sided
Volumes de sombra são usados para desenhar sombras com o buffer de estêncil. O aplicativo calcula os volumes de sombra projetados por geometria de oclusão, computando as bordas da silhueta e extrudindo-as no sentido oposto à luz em um conjunto de volumes 3D. Esses volumes são renderizados duas vezes no buffer de estêncil.
A primeira renderização desenha polígonos voltados para frente e incrementa os valores de buffer de estêncil. A segunda renderização desenha os polígonos orientados para trás do volume de sombra e diminui os valores do buffer de stencil. Normalmente, todos os valores incrementados e decrementados se anulam mutuamente. No entanto, a cena já foi renderizada com geometria normal, fazendo com que alguns pixels falhassem no teste de z-buffer durante a renderização do volume de sombra. Os valores deixados no buffer de estêncil correspondem aos pixels que estão na sombra. Esses conteúdos de buffer de estêncil restantes são usados como uma máscara, para misturar um grande e abrangente quad preto na cena. Com o buffer de estêncil agindo como uma máscara, o resultado é que os pixels que estão nas sombras são escurecidos.
Isso significa que a geometria de sombra é desenhada duas vezes por fonte de luz, pressionando a taxa de transferência de vértice da GPU. O recurso de estêncil de dois lados foi projetado para atenuar essa situação. Nessa abordagem, existem dois conjuntos de configurações de stencil (definidos a seguir), um conjunto para os triângulos voltados para a frente e o outro para os triângulos voltados para trás. Dessa forma, para cada luz, é desenhado apenas um único passe por volume de sombra.
Um exemplo de implementação de estêncil de dois lados pode ser encontrado na amostra ShadowVolume10.
Lendo o buffer de Depth-Stencil como uma textura
Um buffer de estêncil de profundidade inativo pode ser lido por um sombreador como uma textura. Um aplicativo que usa um buffer de profundidade e estêncil como textura renderiza em duas passagens: a primeira grava no buffer de profundidade e estêncil, e a segunda lê a partir do buffer. Isso permite que um sombreador compare valores de profundidade ou estêncil gravados anteriormente no buffer em relação ao valor do pixel que está sendo renderizado no momento. O resultado da comparação pode ser usado para criar efeitos como mapeamento de sombra ou partículas suaves em um sistema de partículas.
Para criar um buffer de estêncil de profundidade que pode ser usado como um recurso de estêncil de profundidade e um recurso de sombreador, algumas alterações precisam ser feitas no código de exemplo na seção Criar um recurso de Depth-Stencil .
O recurso de estêncil de profundidade deve ter um formato sem tipo, como DXGI_FORMAT_R32_TYPELESS.
descDepth.Format = DXGI_FORMAT_R32_TYPELESS;
O recurso de estêncil de profundidade deve usar os sinalizadores de associação D3D10_BIND_DEPTH_STENCIL e D3D10_BIND_SHADER_RESOURCE.
descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE;
Além disso, uma exibição de recurso de sombreador precisa ser criada para o buffer de profundidade usando uma estrutura D3D11_SHADER_RESOURCE_VIEW_DESC e ID3D11Device::CreateShaderResourceView. O modo de exibição de recurso de sombreador usará um formato tipado, como DXGI_FORMAT_R32_FLOAT, que é equivalente ao formato sem tipo especificado quando o recurso de profundidade-estêncil foi criado.
Na primeira passagem de renderização, o buffer de profundidade é vinculado conforme descrito na seção Vincular dados Depth-Stencil ao Estágio OM. Observe que o formato passado para D3D11_DEPTH_STENCIL_VIEW_DESC usará um formato tipado, como DXGI_FORMAT_D32_FLOAT. Depois que a primeira renderização passar, o buffer de profundidade conterá os valores de profundidade da cena.
Na segunda passagem de renderização, a função ID3D11DeviceContext::OMSetRenderTargets é usada para definir a exibição de estêncil de profundidade como NULL ou um recurso de estêncil de profundidade diferente e o modo de exibição de recurso de sombreador é passado para o sombreador usando ID3D11EffectShaderResourceVariable::SetResource. Isso permite que o sombreador acesse os valores de profundidade calculados na primeira passagem de renderização. Observe que uma transformação precisará ser aplicada para recuperar valores de profundidade se o ponto de exibição da primeira passagem de renderização for diferente da segunda passagem de renderização. Por exemplo, se uma técnica de mapeamento de sombra estiver sendo usada, a primeira passagem de renderização será da perspectiva de uma fonte de luz, enquanto a segunda passagem de renderização será da perspectiva do visualizador.
Tópicos relacionados
-
de estágios de pipeline (Direct3D 10)