Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. 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 Depth-Stencil Recurso
- Criar Depth-Stencil Estado
- Associar Depth-Stencil Dados ao Estágio OM
Depois de saber como usar o buffer de estêncil de profundidade e o estado de estêncil de profundidade correspondente, consulte técnicas de estêncil avançado.
Criar 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 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 ativam (e desativam) os testes de profundidade e de stencil. Defina DepthEnable para FALSE para desativar o teste de profundidade e impedir a gravação no buffer de profundidade. Defina StencilEnable para FALSE para desativar o teste de estêncil e impedir a gravação no buffer de estêncil (quando DepthEnable é FALSE e StencilEnable é TRUE , o teste de profundidade sempre passa na operação de estêncil).
DepthEnable afecta apenas o estágio de fusão de saída - não afecta o recorte, o viés de profundidade ou a limitação de valores antes que os dados sejam inseridos em um sombreador de pixel.
Vincular dados Depth-Stencil ao estágio OM
Vincule o estado de estêncil de profundidade.
// Bind depth stencil state
pDevice->OMSetDepthStencilState(pDSState, 1);
Vincule o recurso de estêncil de profundidade usando um modo de 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 exibições de destino de renderização pode ser passada para ID3D11DeviceContext::OMSetRenderTargets, no entanto, todas essas exibições de destino de renderização corresponderão 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 renderize 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 antialiasing multisample for usado, todos os destinos de renderização vinculados e buffers de profundidade devem ter as mesmas contagens de amostras.
Quando um buffer é usado como destino de renderização, testes de profundidade-estêncil e múltiplos destinos de renderização não são suportados.
- Até 8 alvos de renderização podem ser vinculados simultaneamente.
- Todos os destinos de renderização devem ter o mesmo tamanho em todas as dimensões (largura e altura e profundidade para 3D ou tamanho de matriz para *Tipos de matriz).
- Cada destino de renderização pode ter um formato de dados diferente.
- As máscaras de gravação controlam quais dados são gravados em um alvo de renderização. As máscaras de escrita de saída controlam, em cada alvo de renderização e a nível de componente, quais dados são gravados nos alvo(s) de renderização.
Técnicas Avançadas de Estêncil
A parte de estêncil do buffer de estêncil de profundidade pode ser usada para criar efeitos de renderização, como composição, dedimensionamento e contorno.
- Composição
- Aplicação de decalques
- Contornos e Silhuetas
- Two-Sided Stencil
- Lendo o buffer de Depth-Stencil como um de textura
Composição
A sua aplicação pode usar o buffer de estêncil para compor imagens 2D ou 3D numa cena 3D. Uma máscara no buffer de estêncil é usada para ocultar uma área da superfície de destino de renderização. As informações 2D armazenadas, como texto ou bitmaps, podem ser gravadas na área ocluída. Como alternativa, a sua aplicação pode renderizar primitivos 3D adicionais para a região mascarada pelo estêncil da superfície de destino de renderização. 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 reflete a imagem da cena 3D atrás do motorista. É essencialmente uma segunda cena 3D composta com a visão para a frente do motorista.
Decalque
As aplicações Direct3D usam decalques para controlar quais pixels de uma imagem primitiva específica são desenhados na 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 em uma estrada, as marcações 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 traseira podem ser renderizados em cima da primitiva frontal e vice-versa. A imagem resultante parece brilhar de quadro para quadro. Este efeito é chamado de z-fighting ou flimmering.
Para resolver este problema, use um estêncil para mascarar a seção da primitiva traseira onde o adesivo aparecerá. Desative o z-buffering e renderize a imagem da primitiva frontal na área mascarada da superfície de destino de renderização.
A mistura de textura múltipla pode ser usada para resolver este problema.
Contornos e Silhuetas
Você pode usar o buffer de estêncil para efeitos mais abstratos, tais como contornos e silhuetas.
Se seu aplicativo fizer duas etapas 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 da primitiva. A aplicação pode então preencher a área mascarada de estêncil da imagem com uma cor sólida, dando à primitiva uma aparência em relevo.
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 a primitiva deve estar. Sua aplicação pode então preencher o buraco com preto para produzir uma silhueta do primitivo.
Two-Sided Stencil
Os Volumes de Sombra são usados para desenhar sombras com o buffer de estêncil. O aplicativo calcula os volumes de sombra lançados pela geometria ocluída, calculando as bordas da silhueta e extrudindo-as da luz em um conjunto de volumes 3D. Esses volumes são então renderizados duas vezes no buffer de estêncil.
A primeira renderização desenha polígonos voltados para a frente e incrementa os valores do buffer de estêncil. A segunda renderização desenha os polígonos voltados para trás do volume de sombra e diminui os valores de buffer de estêncil. Normalmente, todos os valores incrementados e diminuídos anulam-se mutuamente. No entanto, a cena já foi renderizada com geometria normal, fazendo com que alguns pixels falhassem no teste z-buffer à medida que o volume de sombra é renderizado. Os valores deixados no buffer de estêncil correspondem a pixels que estão na sombra. Esses conteúdos restantes do stencil-buffer são usados como uma máscara, para realizar uma fusão alfa de um grande quadrado preto abrangente na cena. Com o stencil buffer a atuar como uma máscara, o resultado é o escurecimento dos pixels nas áreas de sombra.
Isso significa que a geometria da sombra é desenhada duas vezes por fonte de luz, pressionando assim a taxa de transferência do vértice da GPU. O recurso de estêncil de dois lados foi projetado para mitigar essa situação. Nesta abordagem, existem dois conjuntos de estado de estêncil (nomeados abaixo), um definido para os triângulos voltados para a frente e o outro para os triângulos voltados para trás. Desta forma, apenas uma única passagem é desenhada por volume de sombra, por luz.
Um exemplo de implementação de estêncil de dupla face pode ser encontrado no ShadowVolume10 Sample.
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. Uma aplicação que lê um buffer de profundidade-estêncil como uma textura renderiza em duas passagens: a primeira passagem grava no buffer de profundidade-estêncil e a segunda passagem lê a partir do buffer. Isso permite que um sombreador compare valores de profundidade ou estêncil gravados anteriormente no buffer com o 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 moles em um sistema de partículas.
Para criar um buffer de estêncil de profundidade que possa ser usado tanto como um recurso de estêncil de profundidade quanto como um recurso de sombreador, é necessário fazer algumas alterações no código de exemplo da seção Criar um Recurso 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 D3D10_BIND_DEPTH_STENCIL e D3D10_BIND_SHADER_RESOURCE bind.
descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE;
Além disso, é necessário criar uma visualização de recurso de sombreador para o buffer de profundidade, usando uma estrutura D3D11_SHADER_RESOURCE_VIEW_DESC e o método ID3D11Device::CreateShaderResourceView. A exibição de recurso de sombreador usará um formato digitado, como DXGI_FORMAT_R32_FLOAT que é o equivalente ao formato sem tipo especificado quando o recurso de estêncil de profundidade foi criado.
Na primeira passagem de renderização, o buffer de profundidade é vinculado conforme descrito na seção Vincular os dados Depth-Stencil ao Estágio OM. Observe que o formato passou para D3D11_DEPTH_STENCIL_VIEW_DESC. O formato usará um formato digitado, como DXGI_FORMAT_D32_FLOAT. Após a primeira passagem de renderização, o buffer de profundidade conterá os valores de profundidade para a cena.
Na segunda passagem de renderização, a função ID3D11DeviceContext::OMSetRenderTargets é usada para definir a vista de profundidade e estêncil para NULL ou para um recurso de profundidade e estêncil diferente, e a vista de recurso de sombreador é passada para o sombreador usando ID3D11EffectShaderResourceVariable::SetResource. Isso permite que o sombreador procure os valores de profundidade calculados no primeiro passo de renderização. Observe que uma transformação precisará ser aplicada para recuperar valores de profundidade se o ponto de vista do primeiro passo de renderização for diferente do segundo passo de renderização. Por exemplo, se uma técnica de mapeamento de sombra estiver sendo usada, a primeira passagem de renderização será da perspetiva de uma fonte de luz, enquanto a segunda passagem de renderização será da perspetiva do visualizador.
Tópicos relacionados