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.
Respostas:
Eu renderizaria a cena inteira em um buffer de estêncil com o objeto descrito desejado para definir um pouco e para qualquer outra coisa descartar / remover o bit.
Em seguida, elimine a detecção de borda, pois você não precisa disso; em vez disso, você pode aumentar o buffer um pouco. Então, cada objeto cresce um pouco.
A partir daí, o buffer de estêncil pode ter o contorno necessário. É tudo uma questão de garantir que os outros objetos que você está processando estejam desativando os bits no seu buffer de estêncil.
fonte
1) em um objeto de buffer de quadro, você pode executar um sombreador laplaciano na GPU para obter o contorno.
2) você deve usar o buffer de profundidade final ao desenhar seu objeto no FBO, dessa forma, você desenhará apenas a parte visível do seu objeto no FBO, e o laplaciano contornará apenas a parte visível.
fonte
Espero que eu possa esclarecer isso, mas basicamente você precisa fazer um estêncil dos dois objetos como se fossem os dois selecionados, mantendo apenas as áreas na caixa delimitadora do item que você realmente deseja destacar.
Então, basicamente, você cria um buffer de estêncil dos dois objetos selecionados (ou de todos os objetos que ocluem o objeto, realmente ... mas eu não me preocuparia com esses casos, a menos que ele realmente surja muito - se é que as pessoas ocluídas não esperam muita ajuda), então e com um estêncil da caixa delimitadora do seu objeto.
Isso deve obter o efeito que você está procurando.
Como alternativa, você pode simplesmente deixar o resultado 'ruim' e acho que a maioria das pessoas não se importará muito, embora isso dependa dos seus dados / jogo e principalmente do tamanho dos objetos.
fonte