Primeiros passos com o Three.js

Introdução

Usei a Three.js em alguns dos meus experimentos, e ela é ótima para eliminar as dores de cabeça de começar a trabalhar com 3D no navegador. Com ele, é possível criar câmeras, objetos, luzes, materiais e muito mais. Você também pode escolher o renderizador, o que significa que pode decidir se quer que a cena seja renderizada usando a tela do HTML 5, o WebGL ou o SVG. E, como é de código aberto, você pode até se envolver no projeto. Mas, por enquanto, vou me concentrar no que aprendi brincando com ele como um mecanismo e falar sobre alguns conceitos básicos.

Por mais incrível que seja o Three.js, pode haver momentos em que você pode ter dificuldades. Normalmente, você vai precisar passar bastante tempo com os exemplos, fazer engenharia reversa e (no meu caso, com certeza) procurar funcionalidades específicas e, às vezes, fazer perguntas no GitHub. Se você tiver dúvidas, o Mr. doob e o AlteredQualia são extremamente úteis.

1. Noções básicas

Vou presumir que você tenha pelo menos um conhecimento superficial de 3D e uma proficiência razoável em JavaScript. Se não, talvez seja bom aprender um pouco antes de tentar usar esses recursos, já que eles podem ser um pouco confusos.

No nosso mundo 3D, vamos ter alguns dos seguintes elementos, que vou orientar você no processo de criação:

  1. Uma cena
  2. Um renderizador
  3. Uma câmera
  4. Um ou dois objetos (com materiais)

É claro que você pode fazer algumas coisas legais, e espero que você continue fazendo isso e comece a experimentar o 3D no seu navegador.

2. Suporte

Uma observação rápida sobre o suporte nos navegadores. Na minha experiência, o navegador Chrome do Google é o melhor para trabalhar em termos de quais renderizadores são aceitos e a velocidade do mecanismo JavaScript. O Chrome oferece suporte a Canvas, WebGL e SVG e é extremamente rápido. O Firefox fica em segundo lugar, com o advento da versão 4. O mecanismo de JavaScript parece ser um pouco mais lento que o do Chrome, mas, novamente, o suporte a tecnologias de renderização é ótimo. O Opera e o Safari estão no processo de adicionar suporte ao WebGL, mas as versões atuais só oferecem suporte a canvas. O Internet Explorer (versão 9+) oferece suporte apenas à renderização de tela, e não ouvi nada sobre a Microsoft planejar adicionar recursos do WebGL.

3. Montar o cenário

Vamos supor que você tenha escolhido um navegador compatível com todas as tecnologias de renderização e que você queira renderizar com canvas ou WebGL, já que são as opções mais padronizadas. O Canvas tem mais suporte do que o WebGL, mas vale ressaltar que o WebGL é executado na GPU da placa de vídeo, o que significa que a CPU pode se concentrar em outras tarefas que não são de renderização, como qualquer física ou interação do usuário que você esteja tentando fazer.

Independentemente do renderizador escolhido, é preciso lembrar que o JavaScript precisa ser otimizado para desempenho. O 3D não é uma tarefa leve para um navegador (e é incrível que isso seja possível). Portanto, entenda onde estão os gargalos no código e remova-os se possível.

Dito isso, e supondo que você tenha feito o download e incluído o three.js no seu arquivo HTML, como configurar uma cena? Assim:

// set the scene size
var WIDTH = 400,
HEIGHT = 300;

// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;

// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');

// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
                VIEW_ANGLE,
                ASPECT,
                NEAR,
                FAR );

var scene = new THREE.Scene();

// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;

// start the renderer
renderer.setSize(WIDTH, HEIGHT);

// attach the render-supplied DOM element
$container.append(renderer.domElement);

Não é muito complicado, na verdade.

4. Como criar uma malha

Então, temos uma cena, uma câmera e um renderizador (escolhi um WebGL no meu código de exemplo), mas não temos nada para desenhar. O Three.js tem suporte para carregar alguns tipos de arquivos padrão diferentes, o que é ótimo se você estiver gerando modelos do Blender, Maya, Cinema4D ou qualquer outra coisa. Para simplificar (afinal, é sobre começar!) Vou falar sobre primitivos. Primitivas são malhas geométricas, relativamente básicas, como esferas, planos, cubos e cilindros. O Three.js permite criar estes tipos de primitivas com facilidade:

// set up the sphere vars
var radius = 50, segments = 16, rings = 16;

// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius,
segments,
rings),

sphereMaterial);

// add the sphere to the scene
scene.add(sphere);

Tudo bem, mas e o material da esfera? No código, usamos uma variável sphereMaterial, mas ainda não a definimos. Primeiro, precisamos falar sobre os materiais com mais detalhes.

5. Materiais

Sem dúvida, essa é uma das partes mais úteis do Three.js. Ele oferece vários materiais comuns (e muito úteis) para aplicar às suas malhas:

  1. "Básico", que significa que ele renderiza "sem iluminação".
  2. Lambert
  3. Phong

Há mais, mas, novamente, para simplificar, vou deixar que você descubra por conta própria. No caso do WebGL, esses materiais podem ser muito úteis. Por quê? Porque no WebGL, você precisa escrever sombreadores para tudo que está sendo renderizado. Os sombreadores são um tópico enorme, mas, em resumo, eles são programados em GLSL (OpenGL Shader Language), que informa à GPU como algo deve ficar. Isso significa que você precisa imitar a matemática da iluminação, reflexão e assim por diante. Isso pode ficar muito complicado muito rápido. Graças ao Three.js, você não precisa fazer isso se não quiser, porque ele abstrai isso para você. No entanto, se você quiser escrever shaders, também poderá fazer isso com um MeshShaderMaterial, então é uma configuração flexível.

Por enquanto, vamos aplicar um material de Lambert à esfera:

// create the sphere's material
var sphereMaterial = new THREE.MeshLambertMaterial(
{
// a gorgeous red.
color: 0xCC0000
});

Vale ressaltar que há outras propriedades que podem ser especificadas ao criar um material além da cor, como mapas de ambiente ou de suavização. Confira a página da Wiki para ver as várias propriedades que podem ser definidas nos materiais e, na verdade, em qualquer objeto fornecido pelo mecanismo. Além disso, o threejs.org foi lançado recentemente, o que oferece uma visualização mais atraente da API.

6. Luzes!

Se você renderizar a cena agora, vai aparecer um círculo vermelho. Mesmo que tenhamos um material Lambert aplicado, não há luz na cena. Por padrão, o Three.js voltará a uma luz ambiente completa, que é a mesma que a coloração plana. Vamos corrigir isso com um ponto de luz simples:

// create a point light
var pointLight = new THREE.PointLight( 0xFFFFFF );

// set its position
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;

// add to the scene
scene.add(pointLight);

7. Renderizar

Agora temos tudo configurado para renderizar. Mas, na verdade, precisamos fazer isso:

// draw!
renderer.render(scene, camera);

Você provavelmente vai querer renderizar mais de uma vez. Portanto, se você for fazer um loop, use requestAnimationFrame. Essa é de longe a maneira mais inteligente de processar animações no navegador. Ele ainda não tem suporte total, então recomendo que você confira o shim de Paul Irish.

8. Propriedades de objeto comuns

Se você analisar o código do Three.js, vai notar que muitos objetos "herdam" do Object3D. Esse é um objeto base que contém algumas propriedades muito úteis, como informações de posição, rotação e escala. Em particular, nossa esfera é uma malha que herda do Object3D, a que ela adiciona as próprias propriedades: geometria e materiais. Por que menciono isso? É improvável que você queira apenas ter uma esfera na tela que não faça nada. Essas propriedades valem a pena investigar, porque permitem manipular os detalhes subjacentes das malhas e dos materiais em tempo real.

// sphere geometry
sphere.geometry

// which contains the vertices and faces
sphere.geometry.vertices // an array
sphere.geometry.faces // also an array

// its position
sphere.position // has x, y and z properties
sphere.rotation // same
sphere.scale // ... same

9. Dirty Little Secrets

Só queria apontar rapidamente um problema para o Three.js, que é que, se você modificar, por exemplo, os vértices de uma malha, vai notar no loop de renderização que nada muda. Por quê? Porque o Three.js (pelo que eu sei) armazena em cache os dados de uma malha como uma otimização. O que você precisa fazer é sinalizar para o Three.js que algo mudou para que ele possa recalcular o que for necessário. Para isso, faça o seguinte:

// changes to the vertices
sphere.geometry.__dirtyVertices = true;

// changes to the normals
sphere.geometry.__dirtyNormals = true;

Há mais, mas esses dois que encontrei são os mais úteis. Obviamente, você só deve sinalizar as coisas que mudaram para evitar cálculos desnecessários.

Conclusão

Espero que esta breve introdução ao Three.js tenha sido útil. Não há nada como colocar a mão na massa e tentar algo, e eu recomendo muito. O 3D executado de forma nativa no navegador é muito divertido, e usar um mecanismo como o Three.js elimina muitas dores de cabeça e permite que você crie coisas muito legais. Para ajudar você, agrupei o código-fonte neste artigo do laboratório para que você possa usá-lo como referência. Se você gostou, entre em contato pelo Twitter. É sempre bom saber como você está.