ine 5341

Programa

OpenGL

Trabalhos 2001

Trabalhos 2002

Links

Bibliografia

Plano de Ensino

Parte II - Computação Gráfica Avançada

Visualização Realística em 3D, z-Buffering e Raytracing


Brevíssimo Tutorial de POV-Ray


Objetivos

Esta página visa oferecer um brevíssimo turorial de renderização com POV-Ray. O material fornecido pelos autores juntamente com POV-Ray é tão completo e tão bem estruturado, que um outro tutorial é quase que desnecessário.  Estamos fornecendo este material aqui para você ter uma idéia rápida das facilidades oferecidas pelo POV-Ray.

Para você acessar o material do POV-Team, basta você utilizar o HELP do POV-Ray (caso tenha uma instalação Windows) ou então acessar o Tutorial em www.povray.org.

Neste exemlo nós vamos construir passo a passo a cena abaixo.

A Sintaxe

A Linguagem de Descrição de Cena do POV-Ray possue uma sintaxe muito similar à da Linguagem "C", com comentários, estruturas definindo objetos, blocos definidos por { } e diretivas de inclusão de arquivos iniciadas por #include. Se você já programou em "C" ou Java, não vai ter dificuldade nenhuma em compreender a sintax ed eforma intuitiva a partir dos exemplos que estaremos fornecendo abaixo.

Vamos começar criando um novo arquivo de cena no próprio editor do POV-Ray, clicando em "New" e iniciando o arquvo com a inclusão de um arquivo de definição de cores.

#include "colors.inc"

Definindo uma câmera e uma cor de Fundo

Para podermos renderizar alguma coisa, é necessário definirmos a posição da window. Para tanto utilizaremos a definição de uma câmera, que possui implícitas as definições de ângulo de abertura para projeção em perspectiva, etc.
 

// Camera (Window) posicionada em x=0, y=2, z=-5 voltada para
// direção apontada pelo vetor x=0, y=1, z=2.
camera {
    location <0, 2, -5>
    look_at  <0, 1,  2>
}

Em seguida definimos uma cor de fundo, para que tenhamos pelo menos um "nada" palpável para renderizar. Aqui você vai utilizar as definições de cores que carregou.

// Cor de fundo. Nao e objeto de cena.
background { color Black }

Se você clicar agora no botão "Run" do POV-Ray você vai ver uma cena que é simnplesmente uma janela preta.

Se você fez algum erro de digitação, a linha onde o interpretador do POV-Ray encontrou o erro estará destacada.

Incluindo uma Fonte de Luz

Para podermos renderizar objetos visíveis, é necessário que eles sejam iluminados por alguma fonte de luz. Na forma supersimplificada que Browsers VRML ou que OpenGL trabalham, isto não é necessário, mas em POV=Ray e outros raytracers, é muito importante. Definimos uma fonte de luz da seguinte forma:

// Fonte de Luz Branca posicionada em x=20, y=4 e z=-13  
light_source { <20, 4, -13> color White}

POV-Ray possue muitos tipos de fontes de luz. Este comando simples define uma fonte de luz pontual. Olhe o manual na parte de fontes de luz.

Se você mandar renderizar, vai ver que tudo continua igual....

Definindo Objetos de Dimensões Infinitas como Objetos de Cena

Para fazermos coisas como o "chão" de uma cena ou então a abóbada celeste, POV-Ray oferece vários objetos geométricos de dimensões infinitas. Vamos aqui exemplificar com o plano:

// Plano com textura em xadrez como "chao" da cena
plane { <0, 1, 0>, -1
    pigment {
      checker color Red, color Blue
    }
  }

O atributo pigment permite a você definir as caracterísitcas de cor ou textura do objeto. Neste caso, estamos utilizando o atributo checker que define uma estrutura xadrez e não depende de uma textura definida como bitmap, apenas da definição das suas duas cores.


Objetos Geométricos Simples

POV-Ray define vários objetos geomátricos primitivos, como esferas, cilindros, cubos, cones, etc. Vamos começar com uma esfera vermelha.

// Esfera em x=0, y=1, z=2 com raio=2
sphere {
    <0, 1, 2>, 2
    texture {
      pigment {
        color Red
      }
    }
  }

Observe que não demos nenhum tipo de reflectividade ao objeto e ele portanto possue por default somente reflexão difusa, fácil de ver pela forma como o objeto reage à luz, que vem da direita e ilumina a face direita do objeto, que vai ficando mais escuro à medida que se avança para seu lado esquerdo. Observe que o POV-Ray também renderiza a sobra jogada pelo objeto sobre o plano xadrez que definimos anteriormente.

Dando "Acabamento" aos Objetos

POV-Ray permite que se dê vários tipos de acabamento aos objetos da cena. Os principais são a sobre posição de um bitmap com textura e a definição de características de reflectância. Para tanto, inicie incluindo no início de seu arquivo um arquivo de definição de aparência e de texturas-bitmaps que já vem com o POV-Ray:

#include "textures.inc"

Abra estes arquivos com o editor do POV-Ray para ver o que tem lá dentro. Estão no diretório include.

Vamos agora usar estas definições, primeiramente usando "stones" para dr à esfera uma aparência de madrepérola, redefinido a sua textura:

// Esfera em x=0, y=1, z=2 com raio=2
sphere {
    <0, 1, 2>, 2
    texture {
      pigment {
        White_Marble   // predefinida em textures.inc
        scale 1        // fator de escala da textura
      }
    }
  }

Agora já temos uma coisa mais realista,  esfera parece realmente uma daquelas bolas de pedra que você compra em lojas de lembranças do Brasil em aeroportos... Se você já tentou fazer isso em VRML ou usando OpenGL, você sabe como é difícil de trabalhar com texturas mapeadas em bitmaps nestes ambientes/nesta API. Em POV-Ray isto é bem simples.

O que nos falta é realismo na parte de reflexos de luz. Uma bola d epedra é polida e brilhante. Para tanto o POV-Ray já vem com uma série de definições de reflexo prontas e você pode utilizá-las. Mude seu código para:

// Esfera em x=0, y=1, z=2 com raio=2
sphere {
    <0, 1, 2>, 2
    texture {
      pigment {
        White_Marble   // predefinida em textures.inc
        scale 1        // fator de escala da textura
      }
      finish { Shiny } // predefinida em finish.inc
    }
  }

O arquivo finish.inc é um dos includes-padrão de POV-Ray e não precisa ser incluído manualmente . Abra-o mesmo assim e dê uma olhada par ver como foi definido acabamento chamado shiny.

Observe que agora a superfície da esfera possui reflectância especular e vemos o reflexo brilhante da fonte de luz sobre a esfera.

Trabalhando com Geometria Construtiva

Vimos a Geometria Construtiva na parte de teoria de estruturas de dados 3D e de formas de representação de objetos complexos. POV-Ray dá suporte completo à GC e você pode fazer muitas coisas. Vamos aqui exemplificar as operações de intersecção e de diferença.

Comece apagando a sua esfera do código que você está usando e inclua duas novas esferas vermelhas, circundadas pelo código da operação de intersecção:

intersection {
      sphere { <0, 0, 0>, 1
        translate -0.5*x
     }
      sphere { <0, 0, 0>, 1
        translate 0.5*x
      }
      pigment { Red }
      rotate -30*y     // Para vermos o disco meio de lado
      finish { Shiny } 
}

Com isso criamo duas esferas, empurramos uma para cima da outra por um quarto de seu diâmetro, calculamos a intersecção disto, damos ao resultado a cor vermelha e rotacionamos o resultado em torno de y de -30 graus, de forma a podermos visualizar melhor o resultado. O que nós obtivemos foi uma pastilha, que é exatamente a área interceptada pelas duas esferas.

Agora vamos deixar o exemplo mais complicando, pegando esta intersecção, mas com rotação de 90 graus para deixar a pastilha de frente para nós, e vamos calcular a diferença disso com um cilindro azul:

// Exemplo de Geometria Construtiva
// Diferenca entre um cilindro e o resultado da intersecção de duas esferas.
difference {
    intersection {
      sphere { <0, 0, 0>, 1
        translate -0.5*x
     }
      sphere { <0, 0, 0>, 1
        translate 0.5*x
      }
      pigment { Red }
      rotate 90*y
      finish { Shiny } 
     }
    cylinder { <0, 0, -1> <0, 0, 1>, .35
      pigment { Blue }
    }
  }

O resultado é uma pastilha com um canal de paredes azuis no meio, como mostra a figura:

Incluindo Efeitos Atmosféricos

Através do de uma implementação simples do método da radiância, POV-Ray pode simular muitos efeitos atmosféricos, como névoa, fumaça, etc. Vamos ver aqui uma névoa simples. Para isto apague esta parte de GC e retorne ao código da esfera, criando uma segunda esfera mais atrás, que vai ficar envolta em névoa:

// Esfera em x=0, y=1, z=2 com raio=2
sphere {
    <0, 1, 2>, 2
    texture {
      pigment {
        White_Marble   // predefinida em textures.inc
        scale 1        // fator de escala da textura
      }
      finish { Shiny } // predefinida em finish.inc
    }
  }

// Esfera ao fundo para mais tarde demonstrar efeitos de nevoa
sphere {
    <15, 1, 30>, 2
    texture {
      pigment {Red}
      finish { Shiny } 
    }
  }

Agora inclua o código que define uma frente de névoa:

// Exemplo da implementaçao do calculo de radiancia por POV-Ray
// Efeito de nevoa iniciando-se a 20 unidades da camera com cor cinza 70%
// e transparencia 50% (definida em RGBA - POV-Ray chama de RGBT)
fog {
    distance 20
    color rgbt <0.7 0.7 0.7 0.5>
  }

O resultado é um fundo enevoado, com a segunda esfera emvolta na névoa, como vemos abaixo. Observe que por causa do efeito d eradiância, as sombras se tornam menos nítidas. Veja um dia enevoado e você verá que isso  acontece na realidade.

Trabalhando com Objetos Geométricos mais Flexíveis - A Malha de Polígonos e a Malha de Triângulos

Para a definição de objetos facetas descritos por malhas de polígonos, POV-Ray possue três objetos: 

  • mesh - para triângulos
  • mesh2 - para triângulos gerados por programas de construção geométrica ou reconsrução 3D, é mais rápido do que mesh mas a sintaxe é impossível de ser usada à mão
  • polygon - para malhas de polígonos de qualquer número de pontos.
Nós vamos mostrar um exemplo usando polygon, que será o que você provavelmente utilizará no exercíco no fim deste capítulo. O exemplo é bem simples e foi retirado do tutorila do POV-Ray: criamos um conjunto de polígonos que descreve a palavra POV na cena. O exemplo é auto-explicativo:

// Poligon Mesh (Malha de Poligonos) 
// Simplesmente o texto POV
// Observe que o "furo" no "P" eh automatico
// Para entender desenhe os pontos definindo o poligo que descreve P
polygon {
    30,
    <-0.8, 0.0>, <-0.8, 1.0>,    // Letter "P"
    <-0.3, 1.0>, <-0.3, 0.5>,    // outer shape
    <-0.7, 0.5>, <-0.7, 0.0>,
    <-0.8, 0.0>,
    <-0.7, 0.6>, <-0.7, 0.9>,    // hole
    <-0.4, 0.9>, <-0.4, 0.6>,
    <-0.7, 0.6>
    <-0.25, 0.0>, <-0.25, 1.0>,  // Letter "O"
    < 0.25, 1.0>, < 0.25, 0.0>,  // outer shape
    <-0.25, 0.0>,
    <-0.15, 0.1>, <-0.15, 0.9>,  // hole
    < 0.15, 0.9>, < 0.15, 0.1>,
    <-0.15, 0.1>,
    <0.45, 0.0>, <0.30, 1.0>,    // Letter "V"
    <0.40, 1.0>, <0.55, 0.1>,
    <0.70, 1.0>, <0.80, 1.0>,
    <0.65, 0.0>,
    <0.45, 0.0>
    pigment { color rgb <1, 0, 0> }

    translate x*2
  }

Para ver um exemplo interessante com triângulo, abra o arquivo chessmsh.pov e o arquivo de inclusão chess.inc fornecidos com POV-Ray e você verá o uso e a definição de listas de triângulos. 

Trabalho

Escolha um prédio da UFSC e fotografe-o por todos os lados, medindo também o seu tamanho e o tamanho das janelas, portas etc (isto pode ser feito de forma aproximada). Lembre-se de fotagraf texturas especias, como paredes de tijolos ou mosaicos, com boa resolução. A seguir faça uma modelagem deste prédio e construa uma cena em POV-Ray para renderizá-lo.

O Código Completo do Exemplo

#include "colors.inc"
#include "textures.inc"
#include "stones.inc"

// Cor de fundo. Nao e objeto de cena.
background { color Black }

// Camera (Window) posicionada em x=0, y=2, z=-5 voltada para
// direção apontada pelo vetor x=0, y=1, z=2.
camera {
    location <0, 2, -5>
    look_at  <0, 1,  2>
}

// Fonte de Luz Branca  
light_source { <20, 4, -13> color White}

// Plano com textura em xadrez como "chao" da cena
plane { <0, 1, 0>, -1
    pigment {
      checker color Red, color Blue
    }
  }
 

// Esfera em x=0, y=1, z=2 com raio=2
sphere {
    <0, 1, 2>, 2
    texture {
      pigment {
        White_Marble   // predefinida em textures.inc
        scale 1        // fator de escala da textura
      }
      finish { Shiny } // predefinida em finish.inc
    }
  }

// Esfera ao fundo para mais tarde demonstrar efeitos de nevoa
sphere {
    <15, 1, 30>, 2
    texture {
      pigment {Red}
      finish { Shiny } // pre-defined in finish.inc
    }
  }

/*  box {
    <-1, -0.50,   -1>,  // Near lower left corner
    < 1, 0.0,  3>   // Far upper right corner
    texture {
      T_Grnt1     // Pre-defined from stones.inc
      scale 4       // Scale by the same amount in all
                    // directions
    }
    rotate y*20     // Equivalent to "rotate <0,20,0>"
  }

 */

// Exemplo de Geometria Construtiva
// Diferenca entre um cilindro e o resultado da intersecção de duas esferas.
difference {
    intersection {
      sphere { <0, 0, 0>, 1
        translate -0.5*x
     }
      sphere { <0, 0, 0>, 1
        translate 0.5*x
      }
      pigment { Red }
      rotate 90*y
      finish { Shiny } // pre-defined in finish.inc
     }
    cylinder { <0, 0, -1> <0, 0, 1>, .35
      pigment { Blue }
    }
  }

// Exemplo da implementaçao do calculo de radiancia por POV-Ray
// Efeito de nevoa iniciando-se a 20 unidades da camera com cor cinza 70%
// e transparencia 50% (definida em RGBA - POV-Ray chama de RGBT)
fog {
    distance 20
    color rgbt <0.7 0.7 0.7 0.5>
  }

// Poligon Mesh (Malha de Poligonos) 
// Simplesmente o texto POV
// Observe que o "furo" no "P" eh automatico
// Para entender desenhe os pontos definindo o poligo que descreve P
polygon {
    30,
    <-0.8, 0.0>, <-0.8, 1.0>,    // Letter "P"
    <-0.3, 1.0>, <-0.3, 0.5>,    // outer shape
    <-0.7, 0.5>, <-0.7, 0.0>,
    <-0.8, 0.0>,
    <-0.7, 0.6>, <-0.7, 0.9>,    // hole
    <-0.4, 0.9>, <-0.4, 0.6>,
    <-0.7, 0.6>
    <-0.25, 0.0>, <-0.25, 1.0>,  // Letter "O"
    < 0.25, 1.0>, < 0.25, 0.0>,  // outer shape
    <-0.25, 0.0>,
    <-0.15, 0.1>, <-0.15, 0.9>,  // hole
    < 0.15, 0.9>, < 0.15, 0.1>,
    <-0.15, 0.1>,
    <0.45, 0.0>, <0.30, 1.0>,    // Letter "V"
    <0.40, 1.0>, <0.55, 0.1>,
    <0.70, 1.0>, <0.80, 1.0>,
    <0.65, 0.0>,
    <0.45, 0.0>
    pigment { color rgb <1, 0, 0> }

    translate x*2
  }