Как фронтенд-инженер, который весь день занимается пользовательским интерфейсом, хотите ли вы удивить его или ее кодом на его или ее день рождения?
С тем же успехом вы можете использовать Three.js, чтобы сделать 3D-торт для ta, который одновременно романтичен и демонстрирует очарование вашей технологии.
В этой статье мы научимся рисовать торт с помощью Three.js.
Кодовый адрес:GitHub.com/кварк глюон P…
Основание, связанное с Three.js
Three.js управляет всеми объектами через сцену сцены, а добавленные на сцену объекты также можно разделить на группы:
const scene = new THREE.Scene();
scene.add(xxx);
const group = new THREE.Group();
group.add(yyy);
group.add(zzz);
scene.add(group);
Если вы хотите визуализировать все объекты в сцене, вам нужно указать камеру, а затем использовать средство визуализации для визуализации.Если есть эффект анимации, используйте requestAnimationFrame для непрерывной визуализации кадр за кадром.
const renderer = new THREE.WebGLRenderer();
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
Камера камеры разделена на перспективную камеру PerspectiveCamera, которая смотрит из точки, и ортогональную камеру OrthographicCamera, которая проецируется с поверхности.
Характеристики перспективной камеры в том, что она почти большая и далеко маленькая, а ортогональная - нет, это параллельная проекция, и размер неизменен.
Для трехмерного мира также необходимо указать источник света, иначе он будет полностью черным.Существует много типов источников света, и обычно используются следующие:
- Точечный свет: излучает свет из точки, как лампочка.
- параллельный свет: параллельный свет
- Окружающий свет: равномерно освещает везде
- Прожектор: источник света для сценических прожекторов.
В 3D-сцене существует много видов объектов, например, плоскость, которая всегда обращена к камере, — это спрайт (мы делаем"Цветочный дождь"эффект) и объект, состоящий из треугольников, называемый сеткой.
Чаще используется сетка, она представляет собой геометрию, состоящую из треугольников, и также может быть отображена на каждой поверхности. Итак, есть два параметра: Geometry и Material.
Например, цилиндр — это Mesh, при его создании укажите геометрию цилиндра CylinderBufferGeometry и материал каждой грани.
const 圆柱几何体 = new THREE.CylinderBufferGeometry(上圆半径, 下圆半径, 高度, 侧面分段数量);
const 侧面材质 = new THREE.MeshBasicMaterial({map: 纹理图片});
const 上面材质 = new THREE.MeshBasicMaterial({color: 'red'});
const 下面材质 = new THREE.MeshBasicMaterial({color: 'red'});
const 圆柱 = new THREE.Mesh(圆柱几何体, [侧面材质, 上面材质, 下面材质]);
MeshBasicMaterial — это базовый материал, вы можете указать цвет по цвету или указать текстуру изображения текстуры по карте.
Среди различных мешей особенным является текст, который использует TextGeometry, и текст необходимо загружать из xxx.typeface.json.
И этот файл json можно преобразовать с помощью файла шрифта ttf. использоватьttf на этот сайт typeface.jsonПриходи и уходи:
Затем может отображаться текст:
const fontLoader = new THREE.FontLoader();
fontLoader.load('./font/xxx.typeface.json', function (font) {
var textGeometry = new THREE.TextGeometry('文字', 参数);
const textMaterial = [
new THREE.MeshBasicMaterial({color: '字体颜色'}),
new THREE.MeshBasicMaterial({color: '侧面颜色'}),
];
const text = new THREE.Mesh(textGeometry, textMaterial);
});
Это основы Three.js, которые мы будем использовать, и краткое изложение:
Three.js управляет различными объектами через сцену, а также объекты можно группировать.
Общие объекты включают Mesh и Sprite.Sprite — это плоскость, которая всегда обращена к камере, а Mesh — это трехмерный объект, состоящий из треугольников. Сетка Чтобы указать геометрию Геометрия и материал Материал, обычно используемый материал может быть картой цвета или текстуры. Текст TextGeometry является особенным и требует файла typeface.json, который можно преобразовать с помощью ttf.
После того, как объекты в сцене готовы, вам также необходимо установить источник света Light и камеру Camera.Камера в основном включает в себя перспективную камеру, которая смотрит из точки, и ортогональную камеру, которая проецируется из плоскости.После этого она может рендерером. Объедините requestAnimationFrame для рендеринга кадр за кадром.
Изучив азы, мы официально приступили к рисованию тортов.
Нарисуйте 3D торт
Торт на самом деле состоит из 4 цилиндров плюс текст.Каждый цилиндр имеет разное положение.Боковая, верхняя и нижняя стороны цилиндра наклеены с разными текстурами, что и является тортом.
Сначала приготовим текстуру торта:
Используйте загрузчик текстур TextureLoader для их загрузки:
const cakeTexture1 = new THREE.TextureLoader().load('img/cake1.png');
const cakeTexture2 = new THREE.TextureLoader().load('img/cake2.png');
const cakeTexture3 = new THREE.TextureLoader().load(`img/cake3.png`);
const cakeTexture4 = new THREE.TextureLoader().load('img/cake4.png');
Затем создайте материал для текстурной карты:
const cakeMaterail1 = new THREE.MeshBasicMaterial({map: cakeTexture1});
const cakeMaterail2 = new THREE.MeshBasicMaterial({map: cakeTexture2});
const cakeMaterail3 = new THREE.MeshBasicMaterial({map: cakeTexture3});
const cakeMaterail4 = new THREE.MeshBasicMaterial({map: cakeTexture4});
В дополнение к материалу текстурной карты подготовьте материал, состоящий из цветов:
const pinkMaterial = new THREE.MeshBasicMaterial({color: 'pink'});
Затем создайте 4 цилиндрических объекта (Mesh) с разными материалами текстуры и цвета:
const cakeGeometry1 = new THREE.CylinderBufferGeometry(100, 100, 70, 40);
const cakePart1 = new THREE.Mesh(cakeGeometry1, [cakeMaterail1, pinkMaterial, pinkMaterial]);
Параметры цилиндрической геометрии CylinderBufferGeometry — радиус верхней окружности, радиус нижней окружности, высота и количество делений на стороне.
Радиус круга выше остается прежним, так что это цилиндр. Количество боковых разделений установлено на 40, что более плавно.
Затем установите смещение, а затем вы можете добавить его в группу торта.
Точно так же создаем четыре цилиндра, задаем разные размеры и положения и вставляем разные изображения:
const cakeGeometry1 = new THREE.CylinderBufferGeometry(100, 100, 70, 40);
const cakePart1 = new THREE.Mesh(cakeGeometry1, [cakeMaterail1, pinkMaterial, pinkMaterial]);
cakePart1.translateY(45)
const cakeGeometry2 = new THREE.CylinderBufferGeometry(120, 120, 70, 40);
const cakePart2 = new THREE.Mesh(cakeGeometry2,[cakeMaterail3, pinkMaterial, pinkMaterial]);
cakePart2.translateY(-25)
const cakeGeometry3 = new THREE.CylinderBufferGeometry(140, 140, 60, 40);
const cakePart3 = new THREE.Mesh(cakeGeometry3, [cakeMaterail2, pinkMaterial, pinkMaterial]);
cakePart3.translateY(-90)
const cakeGeometry4 = new THREE.CylinderBufferGeometry(160, 160, 10, 40);
const cakePart4 = new THREE.Mesh(cakeGeometry4, [cakeMaterail4, cakeMaterail4, cakeMaterail4]);
cakePart4.translateY(-120)
cake.add(cakePart1)
cake.add(cakePart2)
cake.add(cakePart3)
cake.add(cakePart4)
Если вы не уверены в положении координат, вы можете добавить в сцену вспомогательный инструмент координат AxisHelper. Параметр - длина оси.
const axisHelper = new THREE.AxisHelper(2500);
scene.add(axisHelper);
Затем идет текстовая часть, которую нужно преобразовать в файл typeface.json через файл шрифта ttf, затем загрузить с помощью fontLoader, а затем создать соответствующий Mesh:
fontLoader.load('./font/guang.typeface.json', function (font) {
var textGeometry = new THREE.TextGeometry('光光', {
font: font,
size: 30,
height: 5,
bevelEnabled: true,
bevelSize: 10,
});
const textMaterial = ['white', 'red'].map(color => new THREE.MeshBasicMaterial({color}));
const text = new THREE.Mesh(textGeometry, textMaterial);
text.translateY(90)
text.translateX(-45)
cake.add(text);
});
В параметрах TextGeometry нужно задать размер шрифта с размером, если толщина по высоте, а край изогнут bevelEnabled, размер и поверхность bevelSize.
Эффект, который мы здесь имеем, заключается в включении поверхности.
После того, как нарисованы 4 цилиндра и нарисован текст, даже если торт нарисован, после установки источника света и камеры его можно визуализировать с помощью Renderer.
Источник света использует окружающий свет из-за равномерного освещения:
const light = new THREE.AmbientLight(0xCCCCCC);
scene.add(light);
В камере используется орфографическая камера, потому что эффект перспективы не нужен:
const width = window.innerWidth;
const height = window.innerHeight;
//窗口宽高比
const k = width / height;
//三维场景显示范围的高度
const s = 200;
const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
camera.position.set(0, 100, 500)
camera.lookAt(scene.position);
Параметры орфографической камеры - трехмерное поле зрения, слева, справа, вверх, вниз, далеко и близко.Высоту указываем 200, а затем вычисляем ширину по соотношению сторон окна. Для дальнего и ближнего можно установить относительно большой диапазон.
Затем вы можете использовать Renderer для рендеринга. Прикрепите отрендеренный холст к корпусу.
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
//设置背景颜色
renderer.setClearColor(0xFFFFFF, 1);
document.body.appendChild(renderer.domElement);
function render() {
renderer.render(scene, camera);
cake.rotation.y += 0.005;
requestAnimationFrame(render)
}
render()
Перед каждым кадром рендера также делается автоматический поворот вокруг оси Y.
Для поддержки ручного вращения это можно сделать напрямую с помощью OrbitControls, контроллера орбиты Three.js.
const controls = new THREE.OrbitControls(camera);
Параметром является камера, потому что это изменение поля зрения достигается за счет изменения положения и ориентации камеры.
После создания каждой части пирога в сцене, установки источника света, камеры, покадрового рендеринга с помощью средства визуализации и добавления контроллера дорожки, который использует мышь для изменения угла обзора, 3D-торт готов.
Давайте посмотрим на эффект:
Кодовый адрес:GitHub.com/кварк глюон P…
Полный код:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生日蛋糕</title>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
<script src="./js/three.js"></script>
<script src="./js/OrbitControls.js"></script>
</head>
<body>
<script>
const width = window.innerWidth;
const height = window.innerHeight;
//窗口宽高比
const k = width / height;
//三维场景显示范围的宽度
const s = 200;
const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
const fontLoader = new THREE.FontLoader();
const scene = new THREE.Scene();
const cake = new THREE.Group();
const renderer = new THREE.WebGLRenderer();
function create() {
renderer.setSize(width, height);
//设置背景颜色
renderer.setClearColor(0xFFFFFF, 1);
document.body.appendChild(renderer.domElement);
camera.position.set(0, 100, 500)
camera.lookAt(scene.position);
const light = new THREE.AmbientLight(0xCCCCCC);
scene.add(light);
const axisHelper = new THREE.AxisHelper(2500);
scene.add(axisHelper);
const cakeTexture1 = new THREE.TextureLoader().load('img/cake1.png');
const cakeTexture2 = new THREE.TextureLoader().load('img/cake2.png');
const cakeTexture3 = new THREE.TextureLoader().load(`img/cake3.png`);
const cakeTexture4 = new THREE.TextureLoader().load('img/cake4.png');
const cakeMaterail1 = new THREE.MeshBasicMaterial({map: cakeTexture1});
const cakeMaterail2 = new THREE.MeshBasicMaterial({map: cakeTexture2});
const cakeMaterail3 = new THREE.MeshBasicMaterial({map: cakeTexture3});
const cakeMaterail4 = new THREE.MeshBasicMaterial({map: cakeTexture4});
const pinkMaterial = new THREE.MeshBasicMaterial({color: 'pink'});
const cakeGeometry1 = new THREE.CylinderBufferGeometry(100, 100, 70, 40);
const cakePart1 = new THREE.Mesh(cakeGeometry1, [cakeMaterail1, pinkMaterial, pinkMaterial]);
cakePart1.translateY(45)
const cakeGeometry2 = new THREE.CylinderBufferGeometry(120, 120, 70, 40);
const cakePart2 = new THREE.Mesh(cakeGeometry2,[cakeMaterail3, pinkMaterial, pinkMaterial]);
cakePart2.translateY(-25)
const cakeGeometry3 = new THREE.CylinderBufferGeometry(140, 140, 60, 40);
const cakePart3 = new THREE.Mesh(cakeGeometry3, [cakeMaterail2, pinkMaterial, pinkMaterial]);
cakePart3.translateY(-90)
const cakeGeometry4 = new THREE.CylinderBufferGeometry(160, 160, 10, 40);
const cakePart4 = new THREE.Mesh(cakeGeometry4, [cakeMaterail4, cakeMaterail4, cakeMaterail4]);
cakePart4.translateY(-120)
cake.add(cakePart1)
cake.add(cakePart2)
cake.add(cakePart3)
cake.add(cakePart4)
fontLoader.load('./font/guang.typeface.json', function (font) {
var textGeometry = new THREE.TextGeometry('光光', {
font: font,
size: 30,
height: 5,
bevelEnabled: true,
bevelSize: 10,
});
const textMaterial = ['white', 'red'].map(color => new THREE.MeshBasicMaterial({color}));
const text = new THREE.Mesh(textGeometry, textMaterial);
text.translateY(90)
text.translateX(-45)
cake.add(text);
});
scene.add(cake);
}
function render() {
renderer.render(scene, camera);
cake.rotation.y += 0.005;
requestAnimationFrame(render)
}
create()
render()
const controls = new THREE.OrbitControls(camera);
</script>
</body>
</html>
Суммировать
В этой статье мы используем Three.js для достижения эффекта 3D-торта.
Прежде всего, мы изучили основы Three.js: управлять объектами через Scene, объекты можно группировать, объекты включают Mesh, Sprite и т. д. Mesh — это 3D-объект, состоящий из треугольников, и Geometry и Material должны быть указаны соответственно. Материалы могут быть текстурными картами или цветами. Сетку текста необходимо преобразовать из ttf в typeface.json, и этот json можно загрузить для отображения текста.
После того, как объект создан, необходимо настроить камеру, освещение и т. д., а затем рендерить кадр за кадром через рендерер.
При отладке вы также можете добавить вспомогательный инструмент системы координат AxisHelper для помощи в разработке.
Затем реализуем 3D-торт:
Он рисуется 4 цилиндрами + текст.Цилиндры используют разные материалы текстурной карты, устанавливают разные позиции, а затем образуют группу тортов.
Устанавливается окружающий свет, используется ортогональная камера, а контроллер орбиты OrbitControls включен для достижения эффекта перетаскивания мыши для изменения положения камеры, тем самым изменяя угол обзора.
В его (ее) день рождения в следующий раз попробуйте с помощью Three.js нарисовать ему (ей) торт, может быть, будет другой урожай.