«Это второй день моего участия в первом испытании обновлений 2022 года. Подробную информацию о мероприятии см.:Вызов первого обновления 2022 г.".
Отказ от ответственности: 3D-модели олимпийских элементов в этой статье являются только для личного исследования, исследования и признательности. Пожалуйста, не модифицируйте, незаконно распространяются, перепечатать, публиковать, коммерциализировать или проводить проведение прочих прибыльных услуг.
задний план
Добро пожаловать на зимние Олимпийские игры и вместе смотрим в будущее!Зимние Олимпийские игры 2022 г.Вот-вот начнется, в этой статье используетсяThree.js + React
Стек технологий для реализации зимних и олимпийских элементов, что делает тему Зимних Олимпийских игр веселой и памятной.3D
страница.本文涉及到的知识点主要包括:TorusGeometry
тор,MeshLambertMaterial
неглянцевый поверхностный материал,MeshDepthMaterial
материал сетки глубины,custromMaterial
индивидуальный материал,Points
частица,PointsMaterial
материал и т.д.
Эффект
Эффект следующий👇
Как показано на анимации, страница в основном состоит из2022
талисман зимних олимпийских игр冰墩墩
, олимпийские кольца, развевающийся флаг🚩
, деревья🌲
и эффект снега❄️
и т.п. состав. Нажмите и удерживайте левую кнопку мыши, чтобы изменить положение камеры, чтобы получить другой вид.
👀
онлайн просмотр:Dragon Ir.github.IO/3/#/ol и MPI...(развернут вGitHub
, может немного медленно загружаться😓
)
выполнить
Представить ресурсы
Сначала представьте библиотеки и внешние ресурсы, необходимые для разработки страницы,OrbitControls
для управления треком объектива,TWEEN
Используется для реализации анимации движения,GLTFLoader
для погрузкиglb
илиgltf
форматированный3D
модели, а также некоторые другие модели, текстуры и другие ресурсы.
import React from 'react';
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { TWEEN } from "three/examples/jsm/libs/tween.module.min.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import bingdundunModel from './models/bingdundun.glb';
// ...
DOM-структура страницы
страницаDOM
Структура очень простая, только рендеринг3D
элементаль#container
контейнер и показ прогресса загрузки.olympic_loading
элемент.
<div>
<div id="container"></div>
{this.state.loadingProcess === 100 ? '' : (
<div className="olympic_loading">
<div className="box">{this.state.loadingProcess} %</div>
</div>
)}
</div>
инициализация сцены
Инициализируйте контейнер рендеринга, сцену, камеру. Для получения подробных сведений об этой части вы можете обратиться к моим предыдущим статьям, которые не будут повторяться в этой статье.
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
scene = new THREE.Scene();
scene.background = new THREE.TextureLoader().load(skyTexture);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 30, 100);
camera.lookAt(new THREE.Vector3(0, 0, 0));
Добавить источник света
В этом примере в основном добавлено два источника света:DirectionalLight
Используется для создания теней, регулировки яркости страницы,AmbientLight
Используется для визуализации окружающей атмосферы.
// 直射光
const light = new THREE.DirectionalLight(0xffffff, 1);
light.intensity = 1;
light.position.set(16, 16, 8);
light.castShadow = true;
light.shadow.mapSize.width = 512 * 12;
light.shadow.mapSize.height = 512 * 12;
light.shadow.camera.top = 40;
light.shadow.camera.bottom = -40;
light.shadow.camera.left = -40;
light.shadow.camera.right = 40;
scene.add(light);
// 环境光
const ambientLight = new THREE.AmbientLight(0xcfffff);
ambientLight.intensity = 1;
scene.add(ambientLight);
Управление прогрессом загрузки
использоватьTHREE.LoadingManager
Управляйте ходом загрузки модели страницы и выполняйте некоторые методы, связанные с ходом загрузки, в его функции обратного вызова. Прогресс загрузки страницы в этом примере находится наonProgress
завершено через , когда процесс загрузки страницы100%
когда, выполнитьTWEEN
Анимация движения объектива.
const manager = new THREE.LoadingManager();
manager.onStart = (url, loaded, total) => {};
manager.onLoad = () => { console.log('Loading complete!')};
manager.onProgress = (url, loaded, total) => {
if (Math.floor(loaded / total * 100) === 100) {
this.setState({ loadingProcess: Math.floor(loaded / total * 100) });
// 镜头补间动画
Animations.animateCamera(camera, controls, { x: 0, y: -1, z: 20 }, { x: 0, y: 0, z: 0 }, 3600, () => {});
} else {
this.setState({ loadingProcess: Math.floor(loaded / total * 100) });
}
};
Создайте землю
Бугристый грунт в этом примере используетсяBlender
Создайте модель, затем экспортируйтеglb
Загрузка формата создана. Конечно, вы также можете просто использоватьThree.js
Аналогичный эффект может быть достигнут со встроенной плоской сеткой и карту удара. использоватьBlender
Преимущество самостроительной модели состоит в том, что эффект волнистости земли может быть отрегулирован свободно и визуально.
var loader = new THREE.GLTFLoader(manager);
loader.load(landModel, function (mesh) {
mesh.scene.traverse(function (child) {
if (child.isMesh) {
child.material.metalness = .1;
child.material.roughness = .8;
// 地面
if (child.name === 'Mesh_2') {
child.material.metalness = .5;
child.receiveShadow = true;
}
});
mesh.scene.rotation.y = Math.PI / 4;
mesh.scene.position.set(15, -20, 0);
mesh.scene.scale.set(.9, .9, .9);
land = mesh.scene;
scene.add(land);
});
Создайте талисман зимних Олимпийских игр Бинг Дундун
Теперь добавьте милый талисман зимних Олимпийских игр Панда Бинг Дундун.🐼
, Бингдундун также используетglb
Модель формата загружена. Его оригинальная модель происходит отздесь, после бесплатной модели с этого сайта используется оригинальная модель3D max
Я обнаружил, что его нельзя использовать непосредственно на веб-странице, он должен быть вBlender
Чтобы восстановить эффект рендеринга, вам также необходимо настроить нормаль текстуры модели для преобразования формата модели.
оригинальная модель:
карта ледяного пирса:
Преобразование в модель, поддерживаемую Blender, и настройка нормалей карты модели и добавление текстур в Blender.:
экспортировать в формате glb:
📖
существуетBlender
Добавьте текстуру к модели в учебном портале:Как текстурировать модель в Blender
Внимательно наблюдайте冰墩墩 🐼
Можно обнаружить, что у него есть слой снаружиПрозрачный пластиковый или стеклянный текстурированный корпус, этот эффект может быть достигнут путем изменения параметров материала, таких как прозрачность, металличность, шероховатость и т. д. модели, и, наконец, рендеринга, таких как👆 banner图
Тип показанного эффекта, как показано в следующем коде.
loader.load(bingdundunModel, mesh => {
mesh.scene.traverse(child => {
if (child.isMesh) {
// 内部
if (child.name === 'oldtiger001') {
child.material.metalness = .5
child.material.roughness = .8
}
// 半透明外壳
if (child.name === 'oldtiger002') {
child.material.transparent = true;
child.material.opacity = .5
child.material.metalness = .2
child.material.roughness = 0
child.material.refractionRatio = 1
child.castShadow = true;
}
}
});
mesh.scene.rotation.y = Math.PI / 24;
mesh.scene.position.set(-8, -12, 0);
mesh.scene.scale.set(24, 24, 24);
scene.add(mesh.scene);
});
Создание олимпийских колец
Олимпийские кольца из базовой геометрической модели тораTorusGeometry
Для этого создайте пять торов и настройте их цвет материала и положение, чтобы составитьсиний черный красный желтый зеленыйПоследовательная пятикольцевая структура. Используемый материал с пятью кольцамиMeshLambertMaterial
.
const fiveCycles = [
{ key: 'cycle_0', color: 0x0885c2, position: { x: -250, y: 0, z: 0 }},
{ key: 'cycle_1', color: 0x000000, position: { x: -10, y: 0, z: 5 }},
{ key: 'cycle_2', color: 0xed334e, position: { x: 230, y: 0, z: 0 }},
{ key: 'cycle_3', color: 0xfbb132, position: { x: -125, y: -100, z: -5 }},
{ key: 'cycle_4', color: 0x1c8b3c, position: { x: 115, y: -100, z: 10 }}
];
fiveCycles.map(item => {
let cycleMesh = new THREE.Mesh(new THREE.TorusGeometry(100, 10, 10, 50), new THREE.MeshLambertMaterial({
color: new THREE.Color(item.color),
side: THREE.DoubleSide
}));
cycleMesh.castShadow = true;
cycleMesh.position.set(item.position.x, item.position.y, item.position.z);
meshes.push(cycleMesh);
fiveCyclesGroup.add(cycleMesh);
});
fiveCyclesGroup.scale.set(.036, .036, .036);
fiveCyclesGroup.position.set(0, 10, -8);
scene.add(fiveCyclesGroup);
💡
ТорГеометрический тор
TorusGeometry
Для создания класса кольцевой геометрии.
Конструктор:
TorusGeometry(radius: Float, tube: Float, radialSegments: Integer, tubularSegments: Integer, arc: Float)
-
radius
: Радиус кольца от центра кольца до центра трубы (поперечное сечение). Значение по умолчанию1
. -
tube
: Радиус трубы, значение по умолчанию0.4
. -
radialSegments
: количество сегментов кольца, значение по умолчанию8
. -
tubularSegments
: количество сегментов конвейера, значение по умолчанию6
. -
arc
: Центральный угол кольца (единица измерения — радианы), значение по умолчанию —Math.PI * 2
.
💡
MeshLambertMaterial неглянцевый поверхностный материал
Материал поверхности без блеска без зеркального освещения. Этот материал использует нефибиционныеLambertian
Модель для расчета отражения. Это хорошо имитирует некоторые поверхности (такие как необработанные древесины или камень), но не глянцевые поверхности с зеркальными бликами (такие как окрашенные древесины).
Конструктор:
MeshLambertMaterial(parameters : Object)
-
parameters
: (необязательно) Объект, определяющий внешний вид материала с одним или несколькими свойствами. Отсюда можно передать любые свойства материала.
Создать баннер
Модель флага изsketchfabСкачать, еще нужен флагшток, можноBlender
В середине добавляют столбчатый куб, а соответствующая длина, ширина и высота регулируются для объединения с поверхностью флага.
карта флага:
Флаг добавил анимацию, которую необходимо выполнить в коде для воспроизведения кадра анимации.
loader.load(flagModel, mesh => {
mesh.scene.traverse(child => {
if (child.isMesh) {
child.castShadow = true;
// 旗帜
if (child.name === 'mesh_0001') {
child.material.metalness = .1;
child.material.roughness = .1;
child.material.map = new THREE.TextureLoader().load(flagTexture);
}
// 旗杆
if (child.name === '柱体') {
child.material.metalness = .6;
child.material.roughness = 0;
child.material.refractionRatio = 1;
child.material.color = new THREE.Color(0xeeeeee);
}
}
});
mesh.scene.rotation.y = Math.PI / 24;
mesh.scene.position.set(2, -7, -1);
mesh.scene.scale.set(4, 4, 4);
// 动画
let meshAnimation = mesh.animations[0];
mixer = new THREE.AnimationMixer(mesh.scene);
let animationClip = meshAnimation;
let clipAction = mixer.clipAction(animationClip).play();
animationClip = clipAction.getClip();
scene.add(mesh.scene);
});
создавать деревья
Чтобы обогатить картинку и создать зимнюю атмосферу, я добавил несколько сосен.🌲
как украшение. Очень важно использовать хитрость при добавлении сосен: мы знаем, что, поскольку модель дерева очень сложна и имеет много граней, слишком много граней снизят производительность страницы и вызовут зависания. В данной работе используются следующие две диаграммы👇
Две показанные пересекающиеся грани используются в качестве основы дерева, поэтому дерево имеет только две грани.Использование этого трюка может в значительной степени оптимизировать производительность страницы, а дерево🌲
похоже, есть3D
чувство.
карта материалов:
сделать деревоПрозрачный только в прозрачной части карты, непрозрачный в других местах, и можетСоздавать тени деревьев вместо теней коробок, вам нужно добавить следующее в модель дереваMeshPhysicalMaterial
,MeshDepthMaterial
Два материала, два материала используют одну и ту же текстурную карту, гдеMeshDepthMaterial
добавил в модельcustromMaterial
характеристики.
let treeMaterial = new THREE.MeshPhysicalMaterial({
map: new THREE.TextureLoader().load(treeTexture),
transparent: true,
side: THREE.DoubleSide,
metalness: .2,
roughness: .8,
depthTest: true,
depthWrite: false,
skinning: false,
fog: false,
reflectivity: 0.1,
refractionRatio: 0,
});
let treeCustomDepthMaterial = new THREE.MeshDepthMaterial({
depthPacking: THREE.RGBADepthPacking,
map: new THREE.TextureLoader().load(treeTexture),
alphaTest: 0.5
});
loader.load(treeModel, mesh => {
mesh.scene.traverse(child =>{
if (child.isMesh) {
child.material = treeMaterial;
child.custromMaterial = treeCustomDepthMaterial;
}
});
mesh.scene.position.set(14, -9, 0);
mesh.scene.scale.set(16, 16, 16);
scene.add(mesh.scene);
// 克隆另两棵树
let tree2 = mesh.scene.clone();
tree2.position.set(10, -8, -15);
tree2.scale.set(18, 18, 18);
scene.add(tree2)
// ...
});
Эффект также может быть достигнут от👆
надBanner
Как вы можете видеть на картинке, для того, чтобы картинка выглядела лучше, я отменил отображение теней дерева.
📌
существует3D
При разработке функций некоторые неважные модели оформления могут использовать эту стратегию для оптимизации.
💡
MeshDepthMaterial материал сетки глубины
Материал, рисующий геометрию по глубине. Глубина основана на ближней и дальней плоскостях камеры, причем белая — самая близкая, а черная — самая дальняя.
Конструктор:
MeshDepthMaterial(parameters: Object)
-
parameters
: (необязательно) Объект, определяющий внешний вид материала с одним или несколькими свойствами. Отсюда можно передать любые свойства материала.
специальные свойства:
-
.depthPacking[Constant]
:depth packing
кодировка. По умолчаниюBasicDepthPacking
. -
.displacementMap[Texture]
: карты смещения влияют на положение вершин сетки, и в отличие от других карт, которые влияют только на освещение и тени материала, смещенные вершины могут отбрасывать тени, блокировать другие объекты и действовать как реальная геометрия. -
.displacementScale[Float]
: Насколько сильно карта смещения влияет на меш (черный — отсутствие смещения, белый — максимальное смещение). Если карта смещения не задана, это значение не будет применяться. По умолчанию1
. -
.displacementBias[Float]
: смещение карты смещения по вершинам меша. Если карта смещения не задана, это значение не будет применяться. По умолчанию0
.
💡
cusomMaterial пользовательский материал
добавить в сеткуcustromMaterial
Пользовательские свойства материала для достижения прозрачного периметраpng
Тень области содержимого карты изображения.
Создайте снежинку
Создайте снежинку❄️
, буду использоватьзнание частиц.THREE.Points
— это класс, используемый для создания точек, а также для управления пакетами частиц. В этом примере создан1500
Задается частица снежинка, и для нее задаются случайные координаты, определяющие трехмерное пространство, и случайные скорости горизонтального и вертикального перемещения.
// 雪花贴图
let texture = new THREE.TextureLoader().load(snowTexture);
let geometry = new THREE.Geometry();
let range = 100;
let pointsMaterial = new THREE.PointsMaterial({
size: 1,
transparent: true,
opacity: 0.8,
map: texture,
// 背景融合
blending: THREE.AdditiveBlending,
// 景深衰弱
sizeAttenuation: true,
depthTest: false
});
for (let i = 0; i < 1500; i++) {
let vertice = new THREE.Vector3(Math.random() * range - range / 2, Math.random() * range * 1.5, Math.random() * range - range / 2);
// 纵向移速
vertice.velocityY = 0.1 + Math.random() / 3;
// 横向移速
vertice.velocityX = (Math.random() - 0.5) / 3;
// 加入到几何
geometry.vertices.push(vertice);
}
geometry.center();
points = new THREE.Points(geometry, pointsMaterial);
points.position.y = -30;
scene.add(points);
💡
Точки Частицы
Three.js
средний, дождь🌧️
,Снег❄️
,облако☁️
, звезды✨
И другие общие частицы в жизни могут быть использованыPoints
Имитировать достичь.
Конструктор:
new THREE.Points(geometry, material);
- Конструктор может принимать два параметра: геометрию и материал.Параметры геометрии используются для указания координат положения частиц, а параметры материала используются для форматирования частиц;
- могут быть основаны на простых геометрических объектах, таких как
BoxGeometry
,SphereGeometry
и т.д. как параметры системы частиц; - Вообще говоря, вам нужно указать вершины самостоятельно, чтобы определить положение частиц.
💡
PointsMaterial Материал точки
пройти черезTHREE.PointsMaterial
Вы можете установить параметры атрибута частицы, даPoints
Материал по умолчанию для использования.
Конструктор:
PointsMaterial(parameters : Object)
-
parameters
: (необязательно) Объект, определяющий внешний вид материала с одним или несколькими свойствами. Отсюда можно передать любые свойства материала.
💡
Свойство материала .смешивание
материал.blending
Атрибут в основном управляет методом наложения слияния текстур,.blending
К значениям свойств относятся:
-
THREE.NormalBlending
: По умолчанию -
THREE.AdditiveBlending
: Аддитивный режим слияния -
THREE.SubtractiveBlending
: Режим субтрактивного слияния -
THREE.MultiplyBlending
: Мультипликативный режим слияния -
THREE.CustomBlending
: пользовательский режим слияния, с.blendSrc
,.blendDst
или.blendEquation
комбинация свойств
💡
Свойство материала .sizeAttenuation
Будет ли размер частиц ослаблен глубиной камеры, по умолчаниюtrue
(Только перспективные камеры).
💡
3.js вектор
Маломерный вектор имеет несколько компонент, двумерный векторVector2
имеютx
а такжеy
двухкомпонентный трехмерный векторVector3
имеютx
,y
,z
трехкомпонентный четырехмерный векторVector4
имеютx
,y
,z
,w
четыре компонента.
Связанный API:
-
Vector2
: 2D вектор -
Vector3
: 3D вектор -
Vector4
: 4D вектор
Управление объективом, адаптация зума, анимация
controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0);
controls.enableDamping = true;
// 禁用平移
controls.enablePan = false;
// 禁用缩放
controls.enableZoom = false;
// 垂直旋转角度限制
controls.minPolarAngle = 1.4;
controls.maxPolarAngle = 1.8;
// 水平旋转角度限制
controls.minAzimuthAngle = -.6;
controls.maxAzimuthAngle = .6;
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}, false);
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls && controls.update();
// 旗帜动画更新
mixer && mixer.update(new THREE.Clock().getDelta());
// 镜头动画
TWEEN && TWEEN.update();
// 五环自转
fiveCyclesGroup && (fiveCyclesGroup.rotation.y += .01);
// 顶点变动之后需要更新,否则无法实现雨滴特效
points.geometry.verticesNeedUpdate = true;
// 雪花动画更新
let vertices = points.geometry.vertices;
vertices.forEach(function (v) {
v.y = v.y - (v.velocityY);
v.x = v.x - (v.velocityX);
if (v.y <= 0) v.y = 60;
if (v.x <= -20 || v.x >= 20) v.velocityX = v.velocityX * -1;
});
}
🔗
Полный код:GitHub.com/дракон ИК/3…
Суммировать
💡
Основные новые точки знаний, включенные в эту статью, включают:
-
TorusGeometry
тор -
MeshLambertMaterial
неглянцевый материал поверхности -
MeshDepthMaterial
материал сетки глубины -
custromMaterial
пользовательский материал -
Points
частица -
PointsMaterial
точечный материал - Свойства материала
.blending
,.sizeAttenuation
-
Three.js
вектор
Возможности для дальнейшей оптимизации:
- Добавьте больше интерактивных функций и еще больше оптимизируйте стиль интерфейса;
- Талисман Бинг Дун Дун добавляет скелетную анимацию и может управлять своим движением и взаимодействием с помощью мыши и клавиатуры.
следующее уведомление:
- "
Metahuman
Метачеловек!Three.js
Оптимизация портрета"
Хотите узнать об инициализации сцены, освещении, тенях, базовой геометрии, сетках, материалах и многом другом.
Three.js
Для получения соответствующих знаний вы можете прочитать мои предыдущие статьи. Если вы считаете, что статья полезна для вас, не забудьтеТри ссылки в один клик 👍.
приложение
- [1]. 1000 порошка! Используйте Three.js, чтобы сделать эксклюзивную 3D-медаль 🥇
- [2]. Three.js реализует 3D-творческую страницу китайского Нового года Тигра.
- [3]. Three.js реализует динамический логотип Facebook Metaverse 3D
- [4]. Three.js реализует трехмерную панорамную детективную игру
- [5]. Three.js реализует классные кислотные 3D-страницы
- [6]. Преобразование моделей 3dx в форматы, поддерживаемые блендером