Descomplicar o 3D para a web

Nunops
MCTW_TDW
Published in
9 min readJul 25, 2022

Como era de esperar, no ano de 2022 a tendência de incluir objetos 3D estáticos e animados na web prevalece… As técnicas e tecnologias utilizadas nestes elementos criam experiências de navegação jamais imagináveis e que finalmente se tornaram uma realidade na web de hoje em dia.

Neste artigo vamos poder saber e aprender mais acerca da evolução 3D na web, assim como criar a nossa própria animação em Three.js e WebGl.

Como tudo começou — VRML

VRML Virtual Reality Modeling Language — foi o primeiro formato de ficheiro padrão para representar elementos vetoriais 3D, concebido especialmente para o uso nas plataformas web.

O VRML surgiu por volta dos anos 90 e destacou-se por ser inovador e único para a web durante aquela época - nomeadamente porque suportava geometrias 3D, animações e scripting.

Especialmente na segunda metade dos anos 90, o VRML começou a ganhar cada vez mais popularidade e a conseguir uma utilização na web através da instalação de um plugin… o entusiasmo espalhou-se e envolveu algumas organizações e instituições de referência, de entre as quais a NASA e a SONY.

Mais abaixo está apresentado um excerto de código VRML que permite criar um cone amarelo e uma luz.

Fonte: https://cs.lmu.edu/~ray/notes/vrmlexamples/

# A directional light source, shining down from above.

DirectionalLight {
direction 0 -1 0
}

# A yellow cone rotated about 57 degrees from vertical.

Transform {
rotation 0 0 -1 1
children [
Shape {
appearance Appearance {
material Material {diffuseColor 1 1 0}
}
geometry Cone {
bottomRadius 2
height 8.1
}
}
]
}

No fim dos anos 90, e iníco dos anos de 2000 a Netscape já tinha perdido a guerra dos browsers com a Microsoft, que por sua vez eliminou o seu próprio plugin de VRML. Para além disso, a inclusão do VRML na Internet Explorer também estava completamente fora de questão.

Em 2001 a Web3D.org propôs o X3D, uma nova norma gráfica 3D para a Web destinada a solidificar o VRML e ser incluída nos Web browsers, evitando assim a necessidade da instalação de um plugin… mas isto nunca chegou a concretizar-se. A partir desse momento, para que a VRML continuasse a ser utilizada, os utilizadores tiveram de começar a assumir o risco de instalar um plugin de terceiros, o que não se verificou para o público em geral.

WebGl

Em meados do ano de 2000 o grupo khronos criou o OpenGL ES, uma API de renderização 3D para dispositivos móveis e “embedded systems” (ES), baseado em 3D OpenGL estabelecida há muito tempo, mas optimizada para dispositivos móveis e tablets.

Atualmente, WebGl é muito utilizado na Web, especialmente em websites publicados no Awwwards. Deixo aqui um sneak peak do que é possível criar com WebGl (e Three.js):

https://abramovic-traces-wepresent.wetransfer.com/
https://www.magische-spiegelungen.de/
https://www.thoughtlab.com/
https://unboring.picsart.com/
https://garden-eight.com/

Como é que funciona o WebGl na web?

O WebGl incorpora uma API JavaScript de baixo nível, onde utiliza o elemento HTML5 <canvas></ canvas> sendo por isso acedido através do DOM (Document Object Model).

A gestão de memória é fornecida pela linguagem de JavaScript e como tal, o WebGL corre diretamente nos browsers, sem a necessidade da instalação de um plugin específico para dar uso a todas as potencialidades de hardware do computador.

  1. A primeira coisa a fazer é criar um elemento HTML canvas.
<body>
<canvas id="glCanvas" width="640" height="480"></canvas>
</body>

2. De seguida, através de JavaScript criamos uma função main que irá ser executada quando a página é renderizada.

function main() {
const canvas = document.querySelector("#glCanvas");
// Initialize the GL context
const gl = canvas.getContext("webgl");

// Only continue if WebGL is available and working
if (gl === null) {
alert("Unable to initialize WebGL. Your browser or machine may not support it.");
return;
}

// Set clear color to black, fully opaque
// gl.clearColor(r, g, b, a);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// Clear the color buffer with specified clear color
gl.clear(gl.COLOR_BUFFER_BIT);
}

window.onload = main;

3. Neste ponto, já temos código suficiente para que o contexto WebGL inicialize com sucesso, pronto e à espera de receber conteúdo.

No entanto, este é um resultado desanimador… um canvas de cor preta. Demasiado código para pintar um canvas, certo?

Canvas — resultado final
Canvas — resultado final

No entanto, quando queremos criar algo em WebGl não o fazemos utilizando JavaScript, mas sim, por exemplo, em GLSL (filename.glsl).

GLSL é uma linguagem de shaders de alto nível baseada na linguagem de programação C. Quando falamos em WebGl e GLSL falamos sempre em shaders.

Mas afinal o que são shaders?

Shaders são um conjunto de instruções que são executadas ao mesmo tempo para cada pixel do ecrã. De um modo geral, isto significa que o código que escrevemos tem de se comportar de uma forma diferente de acordo com cada posição de cada pixel.

Like a type press, your program will work as a function that receives a position and returns a color, and when it’s compiled it will run extraordinarily fast. — by The book of shaders.

Existem dois tipos de shaders:

  • Fragment Shader: define as cores RGBA (vermelho, verde, azul, alfa) para cada pixel a ser processado, sendo chamado uma vez por cada pixel. O objetivo do fragment shader é chamar a variável gl_FragColor que é responsável por “pintar” o elemento 3D que estamos a criar.
  • Vertex Shader: manipula as coordenadas num espaço 3D e é chamado uma vez por cada vértice. O objectivo do vertex shader é configurar a variável gl_Position. Esta variável é utilizada para guardar a posição de cada pixel a ser processado no ecrã.

Tanto a variável gl_FragColor como a variável gl_Position são globais e integradas em GLSL, e é preciso instanciar ambas para vermos o elemento 3D no nosso ecrã.

Veremos agora o código necessário para criar um quadrado vermelho, segundo um projeto já existente na plataforma ShaderToy.

vec3 sdfSquare(vec2 uv, float size, vec2 offset) {
float x = uv.x - offset.x;
float y = uv.y - offset.y;
float d = max(abs(x), abs(y)) - size;

return d > 0. ? vec3(1.) : vec3(1., 0., 0.);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord/iResolution.xy; // <0, 1>
uv -= 0.5; // <-0.5,0.5>
uv.x *= iResolution.x/iResolution.y; // fix aspect ratio
vec2 offset = vec2(0.0, 0.0); vec3 col = sdfSquare(uv, 0.2, offset); // Output to screen
fragColor = vec4(col, 1.0);
}
Quadrado vermelho GLSL
Quadrado vermelho GLSL

Mais uma vez, que dor de cabeça, right?!

Ora, mas tudo isto se tornou mais fácil quando Ricardo Cabello lançou em abril de 2010 no GitHub, o Three.js.

Three.js

Three.js is a cross-browser JavaScript library and application programming interface (API) used to create and display animated 3D computer graphics in a web browser using WebGL.

Ora, esta biblioteca veio facilitar muito a criação e animação de elementos 3D na web de uma forma inovadora. Em WebGl para criarmos um quadrado precisamos de 24 linhas de código, usando Three.js precisamos de apenas 4 linhas de código para criarmos um cubo.

Como é que funciona o Three.js?

Para criarmos uma Three.js scene precisamos de 4 elementos:

  • Scene: a cena/ tela three.js;
  • Câmera: funciona como uma câmera que filma a scene e mostra o resultado no ecrã;
  • Renderer: cria um WebGl renderer — um elemento canvas onde será renderizada a three.js scene.
  • Geometria: three.js permite criarmos muitos tipos de geometrias, tanto 2D como 3D, desde cubos, esferas, torus, pentágonos, entre outros. A cada geometria é ainda possível associarmos uma cor e um material (incluindo texturas e imagens).

De um modo geral, em WebGl para criamos uma geometria temos de criar um algoritmo que calcule e crie todos os vértices da geometria 2D ou 3D. Já em Three.js apenas temos que chamar determinadas classes e métodos que irão executar comandos WebGl behind the scenes.

Vamos agora criar a nossa primeira Three.js scene — um cubo.

  1. Criar um ficheiro HTML.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>

2. Aplicarmos estilo ao body e ao elemento canvas para um melhor design da página.

<style>
body { margin: 0; }
canvas {
position: fixed;
top: 0;
left: 0;
}
</style>

3. Adicionarmos o CDN do three.js no fim do body.

<script src=”https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js" integrity=”sha512-dLxUelApnYxpLt6K2iomGngnHO83iUvZytA3YjDUCjT0HDOHKXnVYdf3hU4JjM8uEhxf9nD1/ey98U3t2vZ0qQ==” crossorigin=”anonymous” referrerpolicy=”no-referrer”></script>

4. Abrir uma nova tag script onde iremos colocar o nosso código JavaScript, e de seguida, escrevermos o nosso primeiro código Three.js.

// Create a three.js scene and camera
let scene = new THREE.Scene();
// Perspective camera with a FOV of 75 and with the size of the screen width and height
let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight);

5. Criar o WebGl renderer

let renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.append(renderer.domElement);

6. Criar a geometria e adicioná-la à cena.

// Create a cube with dimensions 1 for width, height, and depth, accordingly
let geometry = new THREE.BoxGeometry(1,1,1);
// Create a material and associate a yellow color to the cube geometry
let material = new THREE.MeshBasicMaterial({color: 0xfcba03});
// Merge the geometry and the material to create the cube
let cube = new THREE.Mesh(geometry,material);
// add the cube to the scene
scene.add(cube);
// Set the cube positions inside the screen. By default the x, y and z coordinates are equal to 0
cube.position.z = -5;
cube.rotation.x = 10;
cube.rotation.y = 5;
// render the scene on the screen
renderer.render(scene, camera);

7. Por fim, podemos animar este cubo de forma a que rode infinitamente na scene.

// function that will rotate the cube on the x a
const animate = () => {
cube.rotation.x += 0.01;

// update the scene with the rotation
renderer.render(scene, camera);
// method tells the browser that you wish to perform an animation and requests that the browser calls a specified function to update an animation before the next repaint
requestAnimationFrame(animate);
}
animate();
Three.js cubo animado
Three.js cubo animado

Para finalizar, vamos dar level up ao que acabamos de criar, e por isso, iremos criar uma experiência 3D única onde aplicaremos conceitos de Three.js e WebGl (GlSl).

Tutorial:

Tutorial da animação Three.js e WebGl

A utilização de 3D deve aplicar-se em todos os websites?

Sem dúvida que utilizar 3D num website ou num design o irá tornar único e especial. No entanto, nem todos os websites devem incluir experiências 3D devido ao seu público alvo e propósito.

Por exemplo, será que os websites de e-commerce deverão incluir experiências 3D?

Sim e não.

Imaginemos um website de e-commerce que pertence a um supermercado: demostrar 500 produtos através de 500 objetos 3D irá resultar em muitos problemas de performance no site, causando uma experiência de utilização bastante negativa. Neste caso, a utilização de tecnologias 3D não se adequa.

Por outro lado, quando pretendemos demonstrar um ou um determinado conjunto limitado de produtos e suas características então fará mais sentido utilizar o 3D.

Vejamos o exemplo do website da Google, onde promovem o produto “Google Pixel Buds”.

Google Pixel Buds

Neste exemplo, o utilizador é capaz de interagir e saber mais acerca do produto de uma forma realista e com uma visão 360 graus.

Outra categoria a que cada vez mais assistimos na web, são websites portfolios. A inclusão de tecnologias 3D faz com que o website se torne diferente de todos os outros, e sendo um website no qual o mesmo utilizador não entra todos os dias, o primeiro impacto pode ser muito positivo e surpreendedor.

As tecnologias 3D e o seu potencial no futuro da web.

Atualmente, grande parte das tecnologias que utilizamos todos os dias envolvem 3D, seja através dos nossos telemóveis ou computadores.

Quantos de nós já nos deparamos a usar Realidade Virtual nas aplicações dos nossos telemóveis? Tudo isso envolve 3D.

E mesmo agora, com o início da Web 3.0, mesmo estando a olhar para um ecrã “2D” conseguimos ver tudo em 3D… O virtual está-se a tornar cada vez mais real, e tudo graças às evoluções tecnológicas 3D.

Deste modo, olho para o 3D na web com um grande potencial no futuro e como uma “peça” diferenciadora e única.

--

--