Primeiros passos com o Three.js

Introdução

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

Apesar de todas as maravilhas do Three.js, pode haver momentos em que você tenha dificuldades. Normalmente, você precisará passar bastante tempo com os exemplos, fazendo engenharia reversa e (no meu caso, com certeza) procurando funcionalidades específicas e, ocasionalmente, fazendo perguntas pelo GitHub. Se você precisar fazer perguntas, o Mr. doob e o AlteredQualia são extremamente úteis.

1. Noções básicas

Vou presumir que você tenha pelo menos um conhecimento básico de 3D e uma proficiência razoável em JavaScript. Se não tiver, vale a pena aprender um pouco antes de tentar usar esses recursos, porque eles podem ser um pouco confusos.

No nosso mundo 3D, vamos ter alguns dos seguintes elementos, que vou ensinar você a criar:

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

É claro que você pode fazer coisas legais, e espero que você faça isso e comece a testar o 3D no seu navegador.

2. Suporte

Uma observação rápida sobre a compatibilidade nos navegadores. Na minha experiência, o navegador Chrome do Google é o melhor para trabalhar em termos de renderizadores compatíveis e velocidade do mecanismo JavaScript subjacente. O Chrome é compatível com Canvas, WebGL e SVG e é incrivelmente rápido. O Firefox vem logo atrás, com o lançamento da versão 4. O mecanismo JavaScript parece ser um pouco mais lento que o do Chrome, mas o suporte para as tecnologias de renderização é excelente. O Opera e o Safari estão adicionando suporte ao WebGL, mas as versões atuais deles só são compatíveis com o canvas. O Internet Explorer (versão 9+) só é compatível com a renderização de tela, e não há informações sobre planos da Microsoft para adicionar recursos do WebGL.

3. Todos a postos?

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

Independentemente do renderizador escolhido, lembre-se de que o JavaScript precisa ser otimizado para melhorar o desempenho. O 3D não é uma tarefa leve para um navegador (e é incrível que seja possível), então entenda onde estão os gargalos no seu 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 é tão difícil, sério!

4. Como criar uma malha

Temos uma cena, uma câmera e um renderizador (optei por um WebGL no meu exemplo de código), mas não temos nada para desenhar. O Three.js é compatível com o carregamento de alguns tipos de arquivo padrão, o que é ótimo se você estiver exportando modelos do Blender, Maya, Cinema4D ou qualquer outro software. Para simplificar (afinal, estamos apenas começando!), Vou falar sobre primitivos. As geometrias simples são malhas geométricas, relativamente básicas, como esferas, planos, cubos e cilindros. O Three.js permite criar esses tipos de primitivos 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. "Basic", que significa que ele é renderizado sem iluminação.
  2. Lambert
  3. Phong

Existem mais, mas, para simplificar, vou deixar que você descubra por conta própria. No caso do WebGL, esses materiais podem ser uma salvação. Por quê? Porque na WebGL você precisa escrever sombreadores para tudo que é renderizado. Os sombreadores são um assunto muito amplo, mas, em resumo, eles são escritos em GLSL (OpenGL Shader Language), que informa à GPU como algo deve ser exibido. Isso significa que você precisa imitar a matemática da iluminação, reflexão e assim por diante. As coisas podem ficar muito complicadas rapidamente. 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 sombreadores, também poderá fazer isso com um MeshShaderMaterial, o que torna a configuração flexível.

Por enquanto, vamos aplicar um material lambert à esfera:

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

Também vale a pena destacar que existem outras propriedades que você pode especificar ao criar um material além da cor, como suavização ou mapas de ambiente. Confira a página do Wiki para conhecer as várias propriedades que podem ser definidas nos materiais e, na verdade, em qualquer objeto que o mecanismo oferece. Além disso, o site threejs.org (em inglês) foi lançado recentemente e oferece uma visualização mais atraente da API.

6. Luzes!

Se você renderizasse a cena agora, veria um círculo vermelho. Mesmo que tenhamos um material Lambert aplicado, não há luz na cena. Portanto, por padrão, o Three.js vai reverter para uma luz ambiente completa, que é igual à 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, o que é incrível. Mas precisamos fazer exatamente isso:

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

No entanto, você provavelmente vai querer renderizar mais de uma vez. Portanto, se for fazer um loop, use requestAnimationFrame. É de longe a maneira mais inteligente de lidar com animações no navegador. Ele ainda não é totalmente compatível, então recomendo que você dê uma olhada no 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 de base que contém algumas propriedades muito úteis, como as informações de posição, rotação e escala. Em particular, nossa esfera é uma malha que herda de Object3D, à qual adiciona as próprias propriedades: geometry e materials. Por que estou mencionando isso? É improvável que você queira apenas uma esfera na tela que não faz nada, e vale a pena investigar essas propriedades, porque elas 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. Segredos sujos

Quero destacar um detalhe importante do Three.js: se você modificar, por exemplo, os vértices de uma malha, vai notar que nada muda no loop de renderização. Por quê? Porque o Three.js (até onde sei) armazena em cache os dados de uma malha como uma espécie de otimização. O que você precisa fazer é sinalizar ao 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;

Existem outras, mas essas duas são as mais úteis. Obviamente, você só deve sinalizar o que mudou 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 isso. O 3D nativo 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ê, incluí o código-fonte neste artigo do laboratório para que você possa usá-lo como referência. Se você gostou deste conteúdo, me avise pelo Twitter. É sempre bom receber um oi!