Estou trabalhando na configuração de um esboço ativo no meu mecanismo 3D, um efeito de destaque para personagens ou cenários 3D selecionados na tela. Depois de trabalhar com o buffer de estêncil e obter resultados insatisfatórios (problemas com formas côncavas, espessura do contorno devido à distância da câmera e inconsistências entre meu desktop e laptop), mudei para detecção de borda e amostragem de buffer de quadro e obtive um esboço bastante satisfeito com.
No entanto, não consigo ocultar o contorno quando a malha selecionada está atrás de outra malha. Isso faz sentido, dado o meu processo, já que eu simplesmente renderizo o contorno do sombreador 2D a partir de um buffer de quadro depois de renderizar o restante da cena.
Duas capturas de tela dos meus resultados estão abaixo. O primeiro é um contorno "bom"; o segundo é onde o contorno é visto sobre uma malha que bloqueia a origem do contorno.
O processo de renderização é executado da seguinte maneira: 1) Desenhe apenas o alfa da malha destacada, capturando uma silhueta preta em um buffer de quadro (framebuffer1).
2) Passe a textura do framebuffer1 para um segundo shader que executa a detecção de borda. Capture a borda no framebuffer2.
3) Renderize a cena inteira.
4) Renderize a textura do framebuffer2 na parte superior da cena.
Tenho algumas idéias sobre como realizar e espero obter feedback sobre sua validade ou sobre métodos mais simples ou melhores.
Primeiro, pensei em renderizar a cena inteira em um buffer de quadro e armazenar a silhueta visível da malha destacada no canal alfa (todos brancos salvam onde a malha destacada é visível). Eu realizaria a detecção de borda no canal alfa, renderizaria o buffer do quadro de cena e renderizaria a borda em cima. Resultando em algo como isto:
Para fazer isso, pensei em definir uma definição apenas durante a passagem de renderização do objeto destacado que desenharia todo preto no alfa para qualquer pixel visível.
Minha segunda idéia é usar o atual processo de renderização descrito acima, mas também armazenar as coordenadas X, Y e Z nos canais R, G e B do framebuffer1 ao renderizar a silhueta da malha selecionada. As detecções de borda seriam executadas e armazenadas no framebuffer2, mas eu passaria os valores RGB / XYZ das bordas do alfa para a silhueta. Então, ao renderizar a cena, eu testaria se a coordenada está dentro da borda armazenada no framebuffer2. Nesse caso, testaria a profundidade do fragmento atual para determinar se ele está na frente ou atrás das coordenadas extraídas dos canais RGB (convertidos no espaço da câmera). Se o fragmento estiver na frente das coordenadas de profundidade, ele será renderizado normalmente. Se o fragmento estiver atrasado, ele será renderizado como a cor sólida do contorno.
Estou usando o LibGDX para este projeto e gostaria de oferecer suporte ao WebGL e OpenGL ES, portanto, nenhuma das soluções que envolvem sombreadores de geometria ou funções GLSL mais recentes estão disponíveis para mim. Se alguém pudesse comentar sobre minhas abordagens propostas ou propor algo melhor, eu realmente aprecio isso.