Como posso reduzir o alias no efeito de brilho do contorno?

42

Estou tentando replicar o efeito de contorno brilhante no jogo Left 4 Dead. O efeito faz com que o contorno de um objeto brilhe, mesmo quando o objeto está ocluído. Aqui está uma captura de tela do efeito:

insira a descrição da imagem aqui

Sou capaz de replicar esse efeito no meu programa baseado em OpenGL. Isto é o que estou fazendo atualmente:

  • Crie uma textura de cor e profundidade com metade do tamanho da tela para renderizar os objetos brilhantes
  • Limpe as texturas de cor / profundidade do brilho. A cor é limpa para preto.
  • Para cada objeto brilhante, renderize-o na textura brilho como uma cor sólida
  • Realize um desfoque gaussiano separável na textura de brilho
  • Renderize a cena de resolução máxima normalmente
  • Misture aditivamente a textura de brilho com a cena normal, mas use a textura de profundidade de brilho para mascarar o objeto, deixando apenas o contorno desfocado.

Aqui está uma captura de tela da minha abordagem:

insira a descrição da imagem aqui

Aqui está o shader de fragmento que combina a textura do brilho com a cena:

uniform sampler2D glowColorTex;
uniform sampler2D glowDepthTex;
uniform sampler2D sceneColorTex;
void main()
{
    vec2 uv = gl_TexCoord[0].st;

    vec4 color = texture2D( sceneColorTex, uv);

    float depth = texture2D( glowDepthTex, uv).r;
    if(depth == 1.0) {
        color += 2.0 * texture2D( glowColorTex, uv);
    }

    gl_FragColor = color;
}

Como você pode ver, parece funcionar a maior parte do tempo, mas o alias no esboço é muito ruim.

Alguém tem alguma sugestão para suavizar a borda interna do contorno?

Devo amostrar os valores de profundidade vizinhos de cada pixel e escalar o brilho com base no número de valores de profundidade iguais a 1,0?

Ou existe uma abordagem melhor que produza resultados mais suaves?

flashk
fonte

Respostas:

13

Talvez, em vez de compará-lo com o buffer de profundidade de baixa resolução, você possa usar o teste de estêncil. Ao renderizar a cena normal, você apenas renderiza o objeto que deve brilhar no buffer de estêncil (sem testes de profundidade, eu acho) e depois mistura a textura completa do brilho, mas configura o teste de estêncil para passar apenas onde o buffer de estêncil está definido, mascarando o objeto de alta resolução.

Dessa forma, você obtém a silhueta exata do objeto original, enquanto um suavização das bordas levaria apenas a resultados aproximados, mas talvez isso seja suficiente para você.

Chris diz Restabelecer Monica
fonte
Obrigado, isso definitivamente ajuda. Eu esperava alguma técnica que apoiasse alguma forma de anti-aliasing, mas isso ainda é uma grande melhoria.
flashk