sexta-feira, 2 de junho de 2017

Resultados Finais de PBR

Eis aqui alguns resultados da implementação dos materiais espelho, vidro, e cook-torrance:




E, finalmente, a cena final:


sexta-feira, 14 de abril de 2017

[Renderizando Título]

Depois de programar o Ray Tracer para que ele pegue a informação e cor de onde o raio bate, vamos aplicar a verdadeira, legítima equação de rendring  para gerarmos imagens muito mais realistas, já que vamos considerar a refletância e a emitância, assim a iluminação virá naturalmente. No fim, teremos uma cena gerada simulando os "raios" de luz da vida real.

A primeira etapa é programar o pixel sampling, que significa atirar vários raios de um mesmo pixel, com cada raio saindo com direções levemente diferentes entre si. O tipo de pixel sampling utilizado foi o  uniforme: cada raios sai com um offset aleatório máximo de ±0.5 pixel em x e y em relação ao centro do pixel. Com isso, a imagem gerada na versão anterior já vem mais bela pois o pixel sampling reduz o aliasing:

1 sample por pixel(utilizando offset aleatorio) vs. vários samples por pixel. Número de samples perdidos no tempo. Desconsidere a compressão sebosa.
Mas isso é apenas o primeiro passo. Antes de continuar vamos dar uma investigada na equação de rendering:
Fonte: slides do Prof. Christian
A equação nos diz que a radiância(energia luminosa) de um raio de luz que sai de uma pequena superfície(representado na equação como Lo) é igual à soma da radiância emitida(Le) por essa mesma superfície mais o somatório de todas as radiâncias dos raios de luz que chegam nessa superfície(Li). 

A radiância emitida, ou emitância, pode ser entendida como a quantidade de luz que a superfície emite. Uma superfície que emite luz poderia ser, por exemplo, o bulbo de uma lâmpada acesa ou o Sol. A maioria das superfícies não emite nenhum tipo de luz, por isso as coisas são pretas no escuro(quando não há nenhuma fonte de luz que gere "raios" que podem refletir de superfícies).

A radiância incidente é a radiância que vem de outras direções(Ω): pode ser diretamente de uma fonte de luz ou pode ter sido refletida diversas vezes até chegar no ponto em questão.

No entanto, a radiância incidente depende também do material da superfície(como este reflete/absorve a luz) e também do ângulo de incidência do raio(θ, quanto mais perpendicular o raio de luz da superfície, menor fluxo radiante, e assim, menor a radiância).

O material da superfície é definido e representado pelo fr(ωi, ωr), que é uma função de descreme como raios vindos de uma direção ωi é refletido para uma direção ωr. Cada material possui uma função fr(), chamada mais popularmente de BRDF. É uma descrição matemática de como o material reflete luz.

O cálculo dessa integral é feito através do método de Monte Carlo, um método que utiliza probabilidades. Na nossa implementação, só tomamos um raio incidente por parte de superficie, o que facilita as contas e implementação.

Como o Ray Tracer funciona jogando raios da câmera, é mais simples ter apenas um raio incidente por superfície. Quando um raios é jogado, calcula-se o Lo pegando a emitância do material de onde o raio interseccionou e somamos com a radiância do raio incidente. Já que o Ray Tracer funciona "ao contrário", geramos um raio saindo desse ponto de interseção a uma direção aleatória e pegamos o Lo dele. Notamos que aqui já entramos em recursão. Para não simularmos os raios refletindo infinitamente(e em consequência rodarmos um programa sem fim) definimos um número máximo de vezes(max depth) que um raio saindo da câmera pode refletir nas superfícies. Cada vez que um raio é refletido, há uma possibilidade que ele chegue à fonte de luz, então aquele ponto é iluminado e suas informações de cor são calculadas através de sua BRDF. Se um raios refletir o numero máximo de vezes e não chegar em uma fonte de luz, a radiância daquele raio será nula.

É nesse ponto que vemos a importância do pixel sampling: A chance de um raio chegar em uma fonte de luz pode ser baixa, então vários raios de luz são jogado por pixel, e no final, quando todos os raios já tiverem terminado de refletir na cena, a cor do pixel será uma média das radiâncias de cada raio. Quanto mais samples por pixel, mais provável será que algum raio daquele pixel chegará na luz, gerando uma imagem proporcionalmente mais realista.

O algoritmo, em pseudo linguagem, da equação de rendering, retirados dos slides do Prof. Christian:

Essa parte joga os raios da câmera já com o offset.

Essa é a parte recursiva: o raio é gerado e o Lo é somado. O 2*PI é multiplicado pois faz parte do integrador de Monte Carlo.
Utilizando como cena uma caixa estilo Cornell box, geramos as seguintes imagens, com 64, 256 e 2048 samples por pixel, respectivamente. Todas elas tem um max depth 5.

 
🔝🔝🔝🔝🔝

Tivemos alguns problemas misteriosos que no final das contas eram uma má implementação da câmera e dos algoritmos dos triângulos. Resolvidos estes, o programa funcionou com toda sua elegância.

Para melhorar os resultados, além de aumentar o número de samples por pixel e o max depth, podemos implementar roleta russa, e para facilitar a configuração de cena, implementar a importação de objetos já com as informações de refletância e emitância.

Álbuns da vez(esse foi longo)


sexta-feira, 3 de março de 2017

Triângulo, Câmera, Macaco!

Com o Template de Ray Tracer do professor Christian e o Capítulo 10 do Realistic Ray Tracing de Peter Shirley em mãos, podemos implementar a primitiva Triângulo e o teste de interseção Raio-Triângulo. O código ficou praticamente igual ao do livro, e com um simples teste, observamos que o algoritmo do livro funcionou perfeitamente: 

Pirâmide de Giza em construção, circa 2570 BC

O próximo passo é implementar uma câmera com distorção perspectiva, ou Pinhole Camera, para podermos gerar imagens realistas, já que é com distorção perspectiva que observamos o mundo. Seguindo os slides do professor, foi fácil implementar essa câmera, inicialmente na origem. Além disso, torná-la arbitrária não requiriu nenhuma programação extra, sendo apenas necessário modificar os parâmetros na hora de criar o objeto câmera. Observe:

Ângulo alternativo









Uma pequena mudança que fizemos foi mudar a logica da cor do Template do Ray Tracer original: agora as coisas perto da tela ficam mais claras, e não o contrário. Mais intuitivo!

A possibilidade de renderizar triângulos utilizando uma câmera perspectiva abre as portas para o objetivo supremo destas atividades: Renderizar Suzanne, a famigerada prim(ata)itiva do Blender. Com ajuda da biblioteca Assimp, podemos importar as informações de vértices do modelo no formato .obj do símio e renderizar seus triângulos do jeito que devem ser. Admire:


Um detalhe: originalmente Suzanne é feita de quadriláteros, mas o Assimp, ao importar o arquivo do modelo, transforma os quadriláteros em triângulos, já que estamos trabalhamos com essa primitiva.

O último passo para a perfeição da atividade é atribuir cores aleatórias para cada triângulo. Para fazer isso, adicionamos um atribulo de cor, em RGB, na primitiva triângulo e fizemos a função de interseção retornar a cor da primitiva ao invés da distância. Aprecie:


Uma coisa que notei ao setar a câmera para ângulos bons é que meu código parece estar fora de "escala" em comparação aos programas dos colegas. Algo que deve ser investigado, mas não deve ser nada além de encheção de saco na hora de setar a câmera.

Álbum da vez:

quinta-feira, 2 de fevereiro de 2017

Mergulhando no Mitsuba

As postagens daqui em diante serão sobre a nova disciplina do professor Christian, Physically-Based Rendering(PBR). Este post é sobre a primeira atividade da disciplina: criar uma cena legal, renderizá-la usando um programa de PBR e publicá-la no blog da dupla, que é este aqui. A dupla sou eu e Rafael "Mala" Nunes. Cada um de nós gerou uma cena final utilizando o Mitsuba, escolhido dentre outros softwares, por sugestão do professor. Achamos ele fácil de utilizar, principalmente por ser bem documentado e tendo recebido dicas e sugestões de outros colegas da disciplina. 

A primeira cena, criada por mim, foi feita utilizando 8 esferas de diferentes materiais, um retângulo texturizado que serve como base, um environment map que embeleza e ilumina a cena e um modelo de um dragão chinês que aparentemente é um importante símbolo da cultura chinesa e não deve ser zoado. O dragão é o único objeto da cena que recebeu a característica de subsurface scattering, que simula a absorção dos raios de luz pelo objeto e espalha-os sobre camadas mais interiores. Essa característica requer cálculos extras antes da renderização em si, atrasando a imagem final, mas dá um efeito muito belo.

[Música-tema do Dragon Ball]
A segunda cena, criada por Rafael, é baseada em um exemplo do Mitsuba. Aqui, as fontes de luz são duas: a lâmpada no teto e o cubo na mesa. Desta vez, temos mais objetos importados para a cena, ao invés de usar objetos gerados pelo Mitsuba. Esta cena exalta objetos de vidro e materiais polidos, além de fazer referências sutis a clássicos do Thrash Metal americano. Você consegue identificá-las? 

Olhe com cuidado...
Estes foram os resultados das atividades. Aprendemos a utilizar o Mitsuba e a projetar uma cena utilizando a sintaxe de arquivos XML, que é chata. Vamos utilizar os conhecimentos adquiridos aqui para nos auxiliar em testes futuros com nossos próprias renderizadores. Nos vemos na semana que vem, eu espero!

Álbum da vez: