Projeto Virtual Worlds

Computação Gráfica 3D em C

Arquivos Mensais: abril 2012

Acumulando coisas num buffer…

Um dos passos finais da renderização de um frame, no OpenGL, é o uso do que é conhecido como accumulation buffer. Nesse buffer podemos desenhar diversas cenas com pesos diferentes e, no fim das contas, mostrar o resultado. Isso possibilita a criação, fácil (nem tanto!) de diversos efeitos fotográficos. Dois deles, bem úteis, são motion blur (um “embaçamento” causado por movimento) e depth of field (que é também um “embaçamento” causado por um ponto focal na cena).

Usar o buffer de acumulação, no OpenGL, é bem simples:

glAccum(GL_ACCUM, factor1);
/* Desenha a cena */
glAccum(GL_ACCUM, factor2);
/* Desenha a cena de novo */
glAccum(GL_RESULT, final_factor);

A primeira chamada a glAccum diz que as cores dos próximos “desenhos” serão multiplicados pelo fator factor1 e adicionados ao conteúdo atual do buffer. A segunda chamada faz o mesmo, mas usa o fator factor2. Finalmente a chamada a glAccum com o parâmetro GL_RESULT pega o conteúdo do buffer, multiplica pelo final_factor e o copia para o framebuffer.

Isso é uma super-simplificação do uso do buffer de acumulação, mas dá uma idéia de como ele funciona.

O efeito depth of field, por exemplo, pode ser obtido desenhando a cena de um ponto central e, depois, deslocando a câmera em diversas direções próximas ao ponto central, desenhar a cena outras vezes, acumulando-a com fatores diferentes. O efeito final pode ser mais ou menos como este:

O foco central está entrs os dois robôs, na frente. Os mais “nítidos” na cena.

Isso dá uma idéia de profundidade melhor do que desenhar os robozinhos sem o efeito:

Imagem sem o efeito…

A primeira imagem parece mais “foto-realista”, huh? Pelo menos ela fica melhor numa animação… Repare como as animações da Pixar usam esse recurso extensivamente!

É claro que, antes de poder usar o buffer de acumulação, devemos pedir ao OpenGL que o crie (no meu caso, usando a função glfwOpenWindow), informar as características do buffer (tamanho dos componentes RGB e A, usando a mesma função) e quando quisermos usá-lo, habilitá-lo usando a função glEnable.

No próximo post discutirei algumas implementações do efeito…

UPDATE: Infelizmente (?!) desde o OpenGL 3.0 não existe mais um accumulation buffer. Isso tem que ser feito por shaders!