ThreeJs — основы

от автора

Привет, хочу рассказать основу о том как быстро начать пилить продвинутые приложения с 3d моделями.

Для того чтобы лучше понимать контекст последующего материала ожидается что у тебя уже есть знания js, а также react. Также заранее оговорюсь что буду использовать упрощенное объяснения для наилучшего восприятия.

Содержание

  • Основные сущности threejs

  • Основные части модели

  • Загрузка модели

  • Загрузка анимации

  • Threejs и React

Основные сущности Three.js

Three.js построен вокруг нескольких ключевых сущностей. Разберём их с примерами кода.

Сцена — это контейнер (объект), в который ты помещаешь все объекты: геометрию, свет, модели, эффекты и т.п.

const scene = new THREE.Scene(); scene.background = new THREE.Color(0x222222); // тёмно-серый фон

Камера — это глаз пользователя, который видит сцену. Объекты не отображаются, если они вне поля зрения камеры.

const camera = new THREE.PerspectiveCamera(   75,                             // угол обзора (FOV)   window.innerWidth / window.innerHeight, // соотношение сторон   0.1,                            // ближняя плоскость отсечения   1000                            // дальняя плоскость отсечения ); camera.position.set(0, 1, 5); // камера смотрит с точки (0, 1, 5)

Рендерер — это компонент, который переводит сцену и камеру в пиксели, т.е. отрисовывает результат на HTML-экране. Более подробно разберем во 2 части статьи.

const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); // размеры вьюпорта document.body.appendChild(renderer.domElement); // <canvas> элемент, вставляемый в DOM

Как они работают вместе ?

Ты → создаёшь объекты → добавляешь их в сцену
Камера → “смотрит” на сцену
Рендерер → рисует это в на экране

Так а что же на счет 3d моделей ради которых мы и собрались? Давай разберем их чуть подробнее.

Основные части модели

Что же такое модель ?

3D-модель — это структура, описывающая форму, материалы, текстуры и поведение объекта.

Как ты уже понял по описанию сущность состоит из нескольких компонентов. Давай разберемся в них подробнее.

Геометрия (Geometry) — это форма модели: вершины, грани, координаты и нормали.

  • Вершины (vertices) — точки в 3D-пространстве

  • Грани (faces) — треугольники между вершинами

  • Нормали — направление, в которое “смотрит” поверхность

  • UV — координаты наложения текстур

Более подробно разберем во 2 части статьи

Материалы (Materials) — описывают, как должна выглядеть поверхность: цвет, отражения, прозрачность.

В Threejs есть множество материалов, которые служат абстракцией для наилучшего описания нужного материла. Основной MeshStandardMaterial:

const standardMaterial = new THREE.MeshStandardMaterial({   color: 0xffffff,   metalness: 0.8,   roughness: 0.2 });

MeshStandardMaterial, поддерживает следующие параметры:

  • color

  • roughness

  • metalness

  • emissive

  • alpha (прозрачность)

Для более продвинутых кейсов также существует MeshPhysicalMaterial, данный материал отличается более реалистичным отображением и фактически существует только в рамках threejs, к нему может быть автоматически преобразован материал модели с настройками отражения.

Текстуры (Textures) — это изображения, которые накладываются на материал для создания реалистичности.

Типы текстур:

  • diffuse / baseColor — основной цвет

  • normalMap — фейковая детализация рельефа

  • metalnessMap, roughnessMap - блеск

  • aoMap — ambient occlusion (тени)

  • emissiveMap — подсветка

const textureLoader = new THREE.TextureLoader(); const texture = textureLoader.load('/textures/wood.jpg'); const material = new THREE.MeshStandardMaterial({ map: texture });

Загрузка модели

Загрузка моделей может отличаться в зависимости от формата самой модели. Однако для наиболее популярных форматов подойдет GLTFLoader. В случае более экзотических форматов можно использовать Loader с кастомным поведением

 import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';  const loader = new GLTFLoader(); loader.load('/models/robot.glb', (gltf) => {   scene.add(gltf.scene); }); 

Загрузка анимации

Каждая модель может содержать анимацию, если она была заложена на этапе создания этой модели 3d-дизайнером.

В рамках threejs это можно проверить если модель содержит анимации (gltf.animations.length > 0), используй THREE.AnimationMixer:

let mixer; const clock = new THREE.Clock();  loader.load('/models/fox.glb', (gltf) => {   const model = gltf.scene;   scene.add(model);    mixer = new THREE.AnimationMixer(model);    // Проигрываем первую анимацию   const action = mixer.clipAction(gltf.animations[0]);   action.play(); });  function animate() {   requestAnimationFrame(animate);   const delta = clock.getDelta();   mixer?.update(delta);   renderer.render(scene, camera); } 

Threejs и React

Для работы с Three.js в React чаще всего используется следующие пакеты:

@react-three/fiber — обертка над Three.js через JSX (аналог react-dom, но для WebGL)

@react-three/drei — Набор готовых компонентов: OrbitControls, Stage, Text, Gizmo, Loader и т.д.

@react-three/postprocessing — Эффекты постобработки (bloom, depth of field, glitch и пр.)

import { Canvas } from '@react-three/fiber'; import { OrbitControls, Stage } from '@react-three/drei';  export default function App() {   return (     <Canvas>       <Stage environment="city" intensity={0.6}>         <mesh>           <boxGeometry args={[1, 1, 1]} />           <meshStandardMaterial color="skyblue" />         </mesh>       </Stage>       <OrbitControls />     </Canvas>   ); } 

Как видно из примера буквально в одну строчку кода можно описать нужное поведение. Например OrbitControls позволяет вращать камеру относительно сцены. А Stage добавляет пресет заднего фона с освещением. Работа с моделями также упрощена все настройки оборачиваются в mesh и внутри него описываются геометрия и материал, то есть составные части модели.

Также добавлен хук для упрощенной загрузки моделей — useGLTF

// ModelViewer.jsx import { useGLTF } from '@react-three/drei';  export default function ModelViewer(props) {   const { scene } = useGLTF('/models/robot.glb');   return <primitive object={scene} scale={1.5} {...props} />; }

Далее можно вставить данную компоненту прямо в сцену как и любую другую компоненту в обычном react приложении.

Кроме того добавлен хук для загрузки текстур — useTextures

// CrateModel.jsx import { useGLTF, useTexture } from '@react-three/drei'; import * as THREE from 'three';  export default function CrateModel(props) {   // Загружаем модель   const { nodes } = useGLTF('/models/crate.glb');    // Загружаем текстуры   const textureProps = useTexture({     map: '/textures/crate_diffuse.jpg',     roughnessMap: '/textures/crate_roughness.jpg',     normalMap: '/textures/crate_normal.jpg',   });    // Настройка обёртки текстур (по желанию)   Object.values(textureProps).forEach((tex) => {     tex.wrapS = tex.wrapT = THREE.RepeatWrapping;     tex.repeat.set(1, 1);   });    return (     <mesh       geometry={nodes.Crate.geometry}       {...props}       castShadow       receiveShadow     >       <meshStandardMaterial         {...textureProps}         metalness={0.1}         roughness={1}       />     </mesh>   ); } 

Мы разобрали базу, без которой дальше никуда. Я надеюсь как минимум избавил тебя от переживаний, что работа с моделями это что-то из жанра фантастики и все намного проще чем кажется, если разобраться в ключевых аспектах.

В следующей части копнём глубже: как работает сам WebGL под капотом, что на самом деле делает Three.js и как всё это грамотно оптимизировать, чтобы сцена не лагала даже на мобилках. Будет интересно.


ссылка на оригинал статьи https://habr.com/ru/articles/928072/