Materials Scripts
Autor: Matheus Santana | Publicado: 2011-10-26T23:50:00-03:00


Materials Scripts fornecem a capacidade de definir materiais complexos que podem ser facilmente reutilizados. Ainda que se possa definir todas as configurações de materiais necessários para uma cena através do código - utilizando métodos das classes Material e TextureLayer -, essa é uma tarefa bastante árdua. Em vez disso, podemos armazenar definições de materiais em arquivos de texto que podem ser carregados sempre que necessário.


















Carregando Scripts

Scripts de Material são carregados quando os gerentes de recursos são inicializados (veja o post sobre gerentes de recursos): OGRE procura por arquivos .material em todas as localizações de recursos associadas ao grupo (veja Root::addResourceLocation) e os analisa. Também é possível analisar esses arquivos manualmente através do método MaterialSerializer::parseScript.



É importante perceber que, nesse processo de análise, os materiais não são carregados completamente: apenas as definições são carregadas, mas não as texturas nem outros recursos. Isso se dá por que é comum possuir uma extensa biblioteca de materiais mas utilizar apenas um pequeno subconjunto dela em qualquer cena. Carregar todo material de cada script completamente causaria, portanto, uma sobrecarga desnecessária de memória.



Pode-se acessar um material pré-carregado do jeito comum (MaterialManager::getSingleton().getByName()), mas será preciso chamar o método load antes de usá-lo. OGRE faz isso automaticamente quando são utilizados os métodos comuns para atribuição de materiais a entidades.



Outro ponto importante é que o nome de cada material deve ser único, levando em conta todos os scripts (completos) que são carregados pelo sistema - a justificativa pra isso é que os materiais são sempre identificados por seus nomes.
















Formato

Um único script pode conter a definição para vários materiais. A linguagem para a escrita desses scripts é pseudo-C++, com seções delimitadas por chaves ("{", "}") e comentários de linha iniciados com "//" (não são permitidos comentários de múltiplas linhas). O formato genérico é exibido no exemplo abaixo. Pra começar, são considerados apenas materiais de função-fixa que não usam vértices, geometria ou fragmento de programas. Esses scripts mais complexos serão abordados posteriormente.




//isto é um comentário&nbsp;
material walls/funkywall1
{&nbsp;
&nbsp; &nbsp;//primeiro, a técnica preferível
&nbsp; &nbsp;technique&nbsp;
&nbsp; &nbsp;{&nbsp;
&nbsp; &nbsp; &nbsp; //primeiro passo&nbsp;
&nbsp; &nbsp; &nbsp; pass&nbsp;
&nbsp; &nbsp; &nbsp; {&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ambient 0.5 0.5 0.5&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;diffuse 1.0 1.0 1.0&nbsp;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//unidade de textura 0&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;texture_unit&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; texture wibbly.jpg
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scroll_anim 0.1 0.0
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wave_xform scale sine 0.0 0.7 0.0 1.0&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//unidade de textura 1&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//(este é um passo com mais de uma textura)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;texture_unit&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; texture wobbly.png&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rotate_anim 0.25&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; colour_op add&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}&nbsp;
&nbsp; &nbsp; &nbsp; }&nbsp;
&nbsp; &nbsp;}&nbsp;
&nbsp; &nbsp;//segunda técnica, pode ser usada para recuperação
&nbsp; &nbsp;//ou level LOD
&nbsp; &nbsp;technique&nbsp;
&nbsp; &nbsp;{
        //etc
&nbsp; &nbsp;}
}


A todo material no script deve ser dado um nome, o que é feito na linha "material &lt;nomeDoMaterial&gt;", antes do primeiro abre chaves. Tal nome deve ser globalmente único e pode incluir caracteres de caminho (como no exemplo) para dividir os materiais logicamente e também para evitar nomes duplicados. Apesar disso, a engine não trata o nome hierarquicamente, mas apenas como uma string. Se houver caracteres em branco no nome de um material, ele deve ser envolto por aspas duplas (ex.: "rocha vermelha").



Obs.: ":" (dois pontos) é o delimitador para especificar cópia de material no script. Assim sendo, o nome de um material não pode conter dois pontos (":").



Um material pode herdar de um material definido anteriormente através do uso dos dois pontos (":") depois do nome do material seguido pela referência ao material do qual ele herdará. De fato, é possível até mesmo herdar apenas partes de um material (o que será abordado em uma postagem futura sobre herança em scripts). Também é possível utilizar variáveis no script, que são sobrescritas nas versões herdeiras (mais sobre isso quando falarmos de variáveis de script).



Um único material pode ser feito por muitas técnicas. Uma técnica é uma maneira de atingir o efeito desejado. Pode-se fornecer mais de uma técnica por uma medida preventiva (plano B) para o caso de uma placa gráfica não possuir capacidade de renderizar através da técnica preferida ou para definir versões de baixo nível de detalhes - que são renderizadas quando objetos estão distantes, racionalizando recursos computacionais.



Cada técnica, por sua vez, pode ser composta por vários passos. Isto é, a renderização completa de um objeto pode ser realizada várias vezes a fim de se obter um efeito de composição. OGRE também pode dividir automaticamente os passos de uma técnica caso a quantidade de unidades de textura utilizadas supere a capacidade de processamento do dispositivo gráfico.



Cada passo possui uma quantidade de atributos de alto nível como, por exemplo, ambiente para ajustar a intensidade e cor da iluminação ambiental refletida pelo material. Algumas dessas opções não se aplicam se você estiver usando programas de vértices. Veremos mais sobre passos de uma técnica em postagens futuras.



Dentro de cada passo pode haver zero ou mais unidades de textura em uso. Elas definem a textura a ser utilizada e, opcionalmente, algumas operações de combinação / blend (que usa multitexturing) e efeitos de textura.



Você pode referenciar programas de vértices e de fragmentos (que equivalem a vertex e pixel shaders) em um passo com um dado conjunto de parâmetros. Programas por si só são declarados em scripts à parte (scripts .programs). Acompanhe as futuras postagens para saber como declarar vertex, geometry e pixel shaders e também como utilizá-los.












Atributos de material de alto nível

As seções mais externas de um script de material não possuem muitos atributos. A maior pate dos parâmetros configuráveis estão nas seções internas. No entanto, as seções externas possuem alguns, que são mencionados a seguir.









lod_distances (deprecated)
Esta opção está obsoleta e foi substituída por lod_values (abaixo).








lod_strategy

Ajusta o nome da estratégia LOD (level of detail) a ser utilizada. O valor padrão "Distance" indica que o nível de detalhes muda de acordo com a distância da câmera. Um outro valor suportado é "PixelCount", que muda o nível de detalhes com base em uma estimativa do número de pixels afetados no espaço da tela.

Formato: lod_strategy &lt;nome&gt;
Padrão: lod_strategy Distance






lod_values

Este atributo define os valores de transição do nível de detalhes para o material. Através da configuração desse atributo, indica-se que se quer que o material mude a técnica que está sendo utilizada de acordo com alguma métrica - como a distância da câmera ou uma aproximação do espaço de tela que está sendo coberto.



O exato significado desses valores são determinados pelo parâmetro escolhido para o atributo lod_strategy. Podem indicar, por exemplo, uma lista de distâncias para a estratégia "Distance" ou uma lista de contagem de pixels para a estratégia "PixelCount". Você deve fornecer uma lista de valores ordenados do mais alto ao mais baixo valor para o nível de detalhes - cada um indicando o ponto em que o material muda para o próximo nível de detalhe.



Implicitamente, todos os materiais ativam o índice 0 para valores de nível de detalhes menores que a primeira entrada da lista. Assim sendo, não é preciso especificar o nível 0 no começo lista. Você deve garantir que existe no mínimo uma técnica com um valor lod_index para cada valor na lista lod_values (ex.: se você especificar três valores, deve ter técnicas para os níveis de detalhes de índices 0, 1, 2 e 3). Observe que é necessário que haja ao menos uma técnica para lod_index 0.



Formato: lod_values &lt;valor1&gt; &lt;valor2&gt; ... &lt;valorN&gt;

Padrão: none



Exemplo: lod_strategy Distance lod_values 300.0 600.5 1200



O&nbsp;exemplo acima faria com que o material utilizasse a melhor técnica no lod_index 0 até uma distância de 300 unidades de mundo, lod_index 1 de 300 a 600, lod_index 2 de 600 a 1200 e lod_index 3 para qualquer distância maior que 1200.





receive_shadows

Este atributo controla quando objetos que utilizam este material podem ter sombras projetadas sobre eles.

Formato: receive_shadows &lt;on / off&gt;
Padrão: on


Quando um objeto deve ou não receber sombras depende de vários fatores. Há uma seção inteira no manual do OGRE só tratando de sombras. Arbitrariamente, pode-se afirmar que um material transparente nunca recebe sombras - tem, portanto esta opção setada como off.




transparency_casts_shadows

Este atributo controla quando materiais transparentes podem receber certos tipos de sombras.



Formato: transparency_casts_shadows &lt;on / off&gt;

Padrão: off



Este é outro atributo que será explicado melhor na seção de sombras. Para ilustrar sua utilização, podemos citar o uso de sombras de textura em que materiais transparentes normalmente não são renderizados na sombra de textura por que eles não devem bloquear a passagem da luz.



set_texture_alias
Este atributo associa um alias de textura a um nome de textura.

Formato: set_texture_alias &lt;nome do alias&gt; &lt;nome da textura&gt;


Este atributo é explicado melhor em uma seção futura do manual, que deve ser coberta por postagens posteriores a esta.