DEV Community

Cover image for Bar Programming #00 - ThreeJS, como criar cenas 3D na web
Thomas Lincoln
Thomas Lincoln

Posted on

Bar Programming #00 - ThreeJS, como criar cenas 3D na web

Hoje, como teste dessa possível série de posts, tudo dependerá da minha disponibilidade de tempo, e de ter um bom assunto para falar. Mas, aqueles que estão aqui, bem vindos ao beta da minha programação de bar, onde falarei um pouco sobre algum assunto de programação, alguma tecnologia, tentando sempre falar de forma descontraída e leve, abstraindo um pouco, para o texto ser tranquilo de ler.

Ps: Todos os links, que usei de referência, irão estar

No post dessa vez, planejo explicar um pouco sobre como funciona a biblioteca threejs, mas antes, daremos um breve contexto sobre o que é o threejs.

O que é ThreeJS?

Three.js é uma biblioteca JavaScript que permite criar e renderizar gráficos 3D na web. Com ela, você pode criar cenas, objetos, luzes, materiais, texturas, animações, efeitos e muito mais, usando apenas o seu navegador.

Um exemplo de projeto usando three.js: Projeto

O Three.js é uma ferramenta poderosa e divertida para criar gráficos 3D na web, mas também tem suas limitações e desafios. Por exemplo, você precisa se preocupar com a compatibilidade dos navegadores, o desempenho, a otimização, a interação, a física, a iluminação, etc.

Hora de programar!

Agora com esse conhecimento em mãos, vamos tentar, fazer algo simples, como um quadrado girando no cenário, será nosso primeiro de muitos mergulhos, pois, gostaria que você volte para outros, agora chega de conversa, e vamos por a mão na massa.

Primeiramente, o html você pode copiar e colar sem dó, apenas prestando atenção que eu linkei um script da própria biblioteca e também um src para o app.js, o qual precisa ser do tipo “module”:

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>A Square</title>
</head>
<body>

    <script type="importmap">
      {
        "imports": {
          "three": "https://unpkg.com/three@0.139.2/build/three.module.js",
          "three/addons/": "https://unpkg.com/three@0.139.2/examples/jsm/"
        }
      }
    </script>
    <script src="app.js" type="module"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

O css também:

body{
    background-color: rgb(20, 19, 19);
    width: 100%;
    height: 100%;
}
Enter fullscreen mode Exit fullscreen mode

Agora, vamos por parte no javascript, primeiro, precisamos criar a nossa cena, que será, basicamente, o ambiente em que trabalharemos. Também precisamos criar uma câmera, pois sem ela não veremos nada e por fim, criar um renderer, que irá renderizar a nossa cena.

Ps: Também adicionaremos os imports iniciais que usaremos.

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight, 0.1, 1000);
let renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
document.body.appendChild( renderer.domElement );
Enter fullscreen mode Exit fullscreen mode

Essa variável scene será extremamente usada, sempre que quisermos adicionar algo na cena, seja um objeto, uma luz, um chão, ect. Tudo será adicionado nela com um método scene.add(o que você quiser adicionar).

Agora, num primeiro momento, criemos um cubo, a explicação para cada item será dada a seguir.

let geometry = new THREE.BoxGeometry(1, 1, 1);
let material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
let cube = new THREE.Mesh(geometry, material);
scene.add(cube);
Enter fullscreen mode Exit fullscreen mode

Bom, primeiro, o objeto precisa ter uma geometria, sendo basicamente um formato, como se fosse o esqueleto dele, depois disso, temos o material, que seria a pele do nosso cubo. Assim, nós juntamos tanto esqueleto e pele, na construção do cubo usando um new THREE.Mesh(geometry, material), e por fim, usando a variável anteriormente criada, nós adicionamos na cena.

Mas no momento, tanto a câmera quanto o cubo, nasceram no mesmo lugar, no 0,0,0. Então, temos algo assim:

Exemplo da situação

Para isso, afastemos um pouco usando o eixo z (caso não entenda direto, pense apenas que estamos andando um pouco para trás ou para frente com a câmera), e também, renderizemos na tela o cubo.

camera.position.z = 5;
renderer.render(scene, camera);
Enter fullscreen mode Exit fullscreen mode

Tá, mas esse cubo ta meio chato e parado não é? Façamos o seguinte, vamos rotacionar ele no eixo x e no y.

cube.rotation.x += 1;
cube.rotation.y += 2;
Enter fullscreen mode Exit fullscreen mode

Com todas essas mudanças, no momento nosso projeto se encontra assim:

Nosso Projeto No Momento


Agora, com nosso cubinho em mão, proponho tentar melhorar a cena, talvez com um pouco de luz e sombra e com alguma animação para finalizar.

Primeiro a animação, que acaba sendo bem simples, lembra que movemos o objeto, chamando um .position.eixo? Então, nós apenas precisamos fazer isso repetidas vezes, para isso, precisamos criar uma função animate() e chamar uma função chamada requestAnimattionFrame:

function animate() {
  requestAnimationFrame(animate);

  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;

  renderer.render(scene, camera);
}

animate();
Enter fullscreen mode Exit fullscreen mode

Agora, adicionemos um plano e rotacionar, para ele ser um chão da nossa cena, apenas para melhorar a visualização.

const planeGeometry = new THREE.PlaneGeometry( 100, 100 );
const planeMaterial = new THREE.MeshStandardMaterial({ color: 0xbcbcbc });

const plane = new THREE.Mesh( planeGeometry, planeMaterial );
plane.rotation.x = -Math.PI / 2; 
plane.position.y -= 5
plane.receiveShadow = true;
scene.add( plane );
Enter fullscreen mode Exit fullscreen mode

Aqui segue o mesmo esquema do cubo, com apenas a adicção de uma rotação, para ele virar um chão mesmo.


Agora, adicionemos luzes e sombras, para isso usamos o seguinte código:

const ambientLight = new THREE.AmbientLight( 0xffffff, 0.5 );
scene.add( ambientLight );

const spotLight = new THREE.SpotLight( 0xffffff, 0.7 );
spotLight.position.set(2, 12, 2);
spotLight.angle = Math.PI / 6;
spotLight.penumbra = 0.5;
spotLight.decay = 1;
spotLight.distance = 0;
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 1;
spotLight.shadow.camera.far = 60;
scene.add( spotLight );
scene.add( spotLight.target );
Enter fullscreen mode Exit fullscreen mode

Coloquei algumas muitas propriedades rs, mas apenas copie elas, você pode ir modificando cada uma delas, mas são bem descritivas, então, teste a vontade.

E por fim, vou apenas adicionar um controle orbital, para podermos visualizar melhor a cena.

const controls = new OrbitControls( camera, renderer.domElement );
Enter fullscreen mode Exit fullscreen mode

Com isso, você poderá rotacionar sua cena, dar zoom, tirar zoom, o que quiser livremente.

Resultado:

Resultado do Projeto

Muito obrigado pela atenção caso tenha chegado até aqui, espero que meu artigo tenha ajudado, qualquer ideia de post ou sugestão, por favor, me informe nos comentários.

Referências

Link do GitHub: https://github.com/ThomasLincoln/ThreejsTests
Link de referência para as luzes: https://sbcode.net/threejs/directional-light-shadow/

Top comments (0)